1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/*
2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright 2013 The Android Open Source Project
3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License");
5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License.
6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at
7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *      http://www.apache.org/licenses/LICENSE-2.0
9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software
11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS,
12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and
14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License.
15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw;
17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.nio.ByteBuffer;
19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/**
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Utility functions to convert between color-spaces.
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Currently these methods are all CPU based native methods. These could be updated in the future
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * to provide other implementations.
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class ColorSpace {
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Convert YUV420-Planer data to RGBA8888.
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * The input data is expected to be laid out in 3 planes. The width x height Y plane, followed
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * by the U and V planes, where each chroma value corresponds to a 2x2 luminance value block.
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * YUV to RGB conversion is done using the ITU-R BT.601 transformation. The output buffer must
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * be large enough to hold the data, and the dimensions must be multiples of 2.
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param input data encoded in YUV420-Planar.
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param output buffer to hold RGBA8888 data.
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param width the width of the image (must be a multiple of 2)
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param height the height of the image (must be a multiple of 2)
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static void convertYuv420pToRgba8888(
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ByteBuffer input, ByteBuffer output, int width, int height) {
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        expectInputSize(input, (3 * width * height) / 2);
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        expectOutputSize(output, width * height * 4);
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        nativeYuv420pToRgba8888(input, output, width, height);
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Convert ARGB8888 to RGBA8888.
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * The input data is expected to be encoded in 8-bit interleaved ARGB channels. The output
52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * buffer must be large enough to hold the data. The output buffer may be the same as the
53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * input buffer.
54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param input data encoded in ARGB8888.
56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param output buffer to hold RGBA8888 data.
57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param width the width of the image
58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param height the height of the image
59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static void convertArgb8888ToRgba8888(
61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ByteBuffer input, ByteBuffer output, int width, int height) {
62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        expectInputSize(input, width * height * 4);
63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        expectOutputSize(output, width * height * 4);
64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        nativeArgb8888ToRgba8888(input, output, width, height);
65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Convert RGBA8888 to HSVA8888.
69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * The input data is expected to be encoded in 8-bit interleaved RGBA channels. The output
71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * buffer must be large enough to hold the data. The output buffer may be the same as the
72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * input buffer.
73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param input data encoded in RGBA8888.
75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param output buffer to hold HSVA8888 data.
76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param width the width of the image
77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param height the height of the image
78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static void convertRgba8888ToHsva8888(
80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ByteBuffer input, ByteBuffer output, int width, int height) {
81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        expectInputSize(input, width * height * 4);
82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        expectOutputSize(output, width * height * 4);
83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        nativeRgba8888ToHsva8888(input, output, width, height);
84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    /**
87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * Convert RGBA8888 to YCbCrA8888.
88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * The input data is expected to be encoded in 8-bit interleaved RGBA channels. The output
90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * buffer must be large enough to hold the data. The output buffer may be the same as the
91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * input buffer.
92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     *
93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param input data encoded in RGBA8888.
94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param output buffer to hold YCbCrA8888 data.
95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param width the width of the image
96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     * @param height the height of the image
97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks     */
98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    public static void convertRgba8888ToYcbcra8888(
99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ByteBuffer input, ByteBuffer output, int width, int height) {
100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        expectInputSize(input, width * height * 4);
101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        expectOutputSize(output, width * height * 4);
102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        nativeRgba8888ToYcbcra8888(input, output, width, height);
103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static void expectInputSize(ByteBuffer input, int expectedSize) {
106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (input.remaining() < expectedSize) {
107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalArgumentException("Input buffer's size does not fit given width "
108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + "and height! Expected: " + expectedSize + ", Got: " + input.remaining()
109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + ".");
110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static void expectOutputSize(ByteBuffer output, int expectedSize) {
114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        if (output.remaining() < expectedSize) {
115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            throw new IllegalArgumentException("Output buffer's size does not fit given width "
116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + "and height! Expected: " + expectedSize + ", Got: " + output.remaining()
117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks                    + ".");
118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        }
119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static native void nativeYuv420pToRgba8888(
122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ByteBuffer input, ByteBuffer output, int width, int height);
123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static native void nativeArgb8888ToRgba8888(
125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ByteBuffer input, ByteBuffer output, int width, int height);
126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static native void nativeRgba8888ToHsva8888(
128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ByteBuffer input, ByteBuffer output, int width, int height);
129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    private static native void nativeRgba8888ToYcbcra8888(
131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks            ByteBuffer input, ByteBuffer output, int width, int height);
132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    static {
134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks        System.loadLibrary("smartcamera_jni");
135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    }
136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks}
138