1f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He/*
2f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * Copyright 2015 The Android Open Source Project
3f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *
4f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * Licensed under the Apache License, Version 2.0 (the "License");
5f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * you may not use this file except in compliance with the License.
6f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * You may obtain a copy of the License at
7f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *
8f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *      http://www.apache.org/licenses/LICENSE-2.0
9f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *
10f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * Unless required by applicable law or agreed to in writing, software
11f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * distributed under the License is distributed on an "AS IS" BASIS,
12f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * See the License for the specific language governing permissions and
14f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * limitations under the License.
15f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He */
16f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He
17f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hepackage android.media;
18f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He
19f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heimport android.graphics.ImageFormat;
20f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heimport android.graphics.PixelFormat;
21f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heimport android.media.Image.Plane;
22f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heimport android.util.Size;
23f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He
24bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun Heimport libcore.io.Memory;
25bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He
26f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heimport java.nio.ByteBuffer;
27f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He
28f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He/**
29f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * Package private utility class for hosting commonly used Image related methods.
30f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He */
31f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heclass ImageUtils {
32f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He
33f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He    /**
34f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * Only a subset of the formats defined in
35f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * {@link android.graphics.ImageFormat ImageFormat} and
36f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * {@link android.graphics.PixelFormat PixelFormat} are supported by
37f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * ImageReader. When reading RGB data from a surface, the formats defined in
38f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * {@link android.graphics.PixelFormat PixelFormat} can be used; when
39f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * reading YUV, JPEG or raw sensor data (for example, from the camera or video
40f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * decoder), formats from {@link android.graphics.ImageFormat ImageFormat}
41f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * are used.
42f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     */
43f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He    public static int getNumPlanesForFormat(int format) {
44f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        switch (format) {
45f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case ImageFormat.YV12:
46f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case ImageFormat.YUV_420_888:
47f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case ImageFormat.NV21:
48f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He                return 3;
49f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case ImageFormat.NV16:
50f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He                return 2;
51f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case PixelFormat.RGB_565:
52f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case PixelFormat.RGBA_8888:
53f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case PixelFormat.RGBX_8888:
54f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case PixelFormat.RGB_888:
55f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case ImageFormat.JPEG:
56f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case ImageFormat.YUY2:
57f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case ImageFormat.Y8:
58f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case ImageFormat.Y16:
59f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case ImageFormat.RAW_SENSOR:
6044581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh            case ImageFormat.RAW_PRIVATE:
61f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            case ImageFormat.RAW10:
62dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He            case ImageFormat.RAW12:
63dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He            case ImageFormat.DEPTH16:
64dc6bb24a3c2c830c909523e8d7d999fb556fb77dZhijun He            case ImageFormat.DEPTH_POINT_CLOUD:
65f7fec7397e37657d08ec6a8c1c214c1f90a77bfdEmilian Peev            case ImageFormat.RAW_DEPTH:
66f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He                return 1;
67d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He            case ImageFormat.PRIVATE:
68f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He                return 0;
69f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            default:
70f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He                throw new UnsupportedOperationException(
71f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He                        String.format("Invalid format specified %d", format));
72f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        }
73f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He    }
74f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He
75f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He    /**
76f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * <p>
77f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * Copy source image data to destination Image.
78f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * </p>
79f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * <p>
80d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He     * Only support the copy between two non-{@link ImageFormat#PRIVATE PRIVATE} format
81d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He     * images with same properties (format, size, etc.). The data from the
82d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He     * source image will be copied to the byteBuffers from the destination Image
83d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He     * starting from position zero, and the destination image will be rewound to
84d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He     * zero after copy is done.
85f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * </p>
86f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     *
87f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * @param src The source image to be copied from.
88f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * @param dst The destination image to be copied to.
89f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     * @throws IllegalArgumentException If the source and destination images
90f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     *             have different format, or one of the images is not copyable.
91f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He     */
92f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He    public static void imageCopy(Image src, Image dst) {
93f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        if (src == null || dst == null) {
94f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            throw new IllegalArgumentException("Images should be non-null");
95f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        }
96f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        if (src.getFormat() != dst.getFormat()) {
97f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            throw new IllegalArgumentException("Src and dst images should have the same format");
98f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        }
99d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He        if (src.getFormat() == ImageFormat.PRIVATE ||
100d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He                dst.getFormat() == ImageFormat.PRIVATE) {
101d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He            throw new IllegalArgumentException("PRIVATE format images are not copyable");
102f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        }
10344581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh        if (src.getFormat() == ImageFormat.RAW_PRIVATE) {
10444581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh            throw new IllegalArgumentException(
10544581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh                    "Copy of RAW_OPAQUE format has not been implemented");
10644581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh        }
107f7fec7397e37657d08ec6a8c1c214c1f90a77bfdEmilian Peev        if (src.getFormat() == ImageFormat.RAW_DEPTH) {
108f7fec7397e37657d08ec6a8c1c214c1f90a77bfdEmilian Peev            throw new IllegalArgumentException(
109f7fec7397e37657d08ec6a8c1c214c1f90a77bfdEmilian Peev                    "Copy of RAW_DEPTH format has not been implemented");
110f7fec7397e37657d08ec6a8c1c214c1f90a77bfdEmilian Peev        }
111f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        if (!(dst.getOwner() instanceof ImageWriter)) {
112f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            throw new IllegalArgumentException("Destination image is not from ImageWriter. Only"
113f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He                    + " the images from ImageWriter are writable");
114f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        }
115f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        Size srcSize = new Size(src.getWidth(), src.getHeight());
116f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        Size dstSize = new Size(dst.getWidth(), dst.getHeight());
117f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        if (!srcSize.equals(dstSize)) {
118f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            throw new IllegalArgumentException("source image size " + srcSize + " is different"
119f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He                    + " with " + "destination image size " + dstSize);
120f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        }
121f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He
122f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        Plane[] srcPlanes = src.getPlanes();
123f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        Plane[] dstPlanes = dst.getPlanes();
124f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        ByteBuffer srcBuffer = null;
125f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        ByteBuffer dstBuffer = null;
126f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        for (int i = 0; i < srcPlanes.length; i++) {
127bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            int srcRowStride = srcPlanes[i].getRowStride();
128bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            int dstRowStride = dstPlanes[i].getRowStride();
129f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            srcBuffer = srcPlanes[i].getBuffer();
130bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            dstBuffer = dstPlanes[i].getBuffer();
131bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            if (!(srcBuffer.isDirect() && dstBuffer.isDirect())) {
132bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                throw new IllegalArgumentException("Source and destination ByteBuffers must be"
133bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        + " direct byteBuffer!");
134bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            }
135bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            if (srcPlanes[i].getPixelStride() != dstPlanes[i].getPixelStride()) {
136bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                throw new IllegalArgumentException("Source plane image pixel stride " +
137bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        srcPlanes[i].getPixelStride() +
138bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        " must be same as destination image pixel stride " +
139bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        dstPlanes[i].getPixelStride());
140bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            }
141bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He
142f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            int srcPos = srcBuffer.position();
143f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            srcBuffer.rewind();
144f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            dstBuffer.rewind();
145bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            if (srcRowStride == dstRowStride) {
146bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                // Fast path, just copy the content if the byteBuffer all together.
147bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                dstBuffer.put(srcBuffer);
148bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            } else {
149bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                // Source and destination images may have different alignment requirements,
150bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                // therefore may have different strides. Copy row by row for such case.
151bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                int srcOffset = srcBuffer.position();
152bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                int dstOffset = dstBuffer.position();
153bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                Size effectivePlaneSize = getEffectivePlaneSizeForImage(src, i);
154bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                int srcByteCount = effectivePlaneSize.getWidth() * srcPlanes[i].getPixelStride();
155bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                for (int row = 0; row < effectivePlaneSize.getHeight(); row++) {
156bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                    if (row == effectivePlaneSize.getHeight() - 1) {
157bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        // Special case for NV21 backed YUV420_888: need handle the last row
158bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        // carefully to avoid memory corruption. Check if we have enough bytes to
159bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        // copy.
160bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        int remainingBytes = srcBuffer.remaining() - srcOffset;
161bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        if (srcByteCount > remainingBytes) {
162bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                            srcByteCount = remainingBytes;
163bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        }
164bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                    }
165bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                    directByteBufferCopy(srcBuffer, srcOffset, dstBuffer, dstOffset, srcByteCount);
166bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                    srcOffset += srcRowStride;
167bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                    dstOffset += dstRowStride;
168bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                }
169bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            }
170bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He
171f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            srcBuffer.position(srcPos);
172f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He            dstBuffer.rewind();
173f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He        }
174f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He    }
17511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen
17611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen    /**
17711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     * Return the estimated native allocation size in bytes based on width, height, format,
17811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     * and number of images.
17911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     *
18011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     * <p>This is a very rough estimation and should only be used for native allocation
18111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     * registration in VM so it can be accounted for during GC.</p>
18211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     *
18311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     * @param width The width of the images.
18411c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     * @param height The height of the images.
18511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     * @param format The format of the images.
18611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     * @param numImages The number of the images.
18711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen     */
18811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen    public static int getEstimatedNativeAllocBytes(int width, int height, int format,
18911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            int numImages) {
19011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen        double estimatedBytePerPixel;
19111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen        switch (format) {
19211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            // 10x compression from RGB_888
19311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.JPEG:
19411c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.DEPTH_POINT_CLOUD:
19511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                estimatedBytePerPixel = 0.3;
19611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                break;
19711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.Y8:
19811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                estimatedBytePerPixel = 1.0;
19911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                break;
20011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.RAW10:
20111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                estimatedBytePerPixel = 1.25;
20211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                break;
20311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.YV12:
20411c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.YUV_420_888:
20511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.NV21:
20644581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh            case ImageFormat.RAW12:
20744581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh            case ImageFormat.PRIVATE: // A rough estimate because the real size is unknown.
20811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                estimatedBytePerPixel = 1.5;
20911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                break;
21011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.NV16:
21111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case PixelFormat.RGB_565:
21211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.YUY2:
21311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.Y16:
214f7fec7397e37657d08ec6a8c1c214c1f90a77bfdEmilian Peev            case ImageFormat.RAW_DEPTH:
21511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.RAW_SENSOR:
21644581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh            case ImageFormat.RAW_PRIVATE: // round estimate, real size is unknown
21711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case ImageFormat.DEPTH16:
21811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                estimatedBytePerPixel = 2.0;
21911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                break;
22011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case PixelFormat.RGB_888:
22111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                estimatedBytePerPixel = 3.0;
22211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                break;
22311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case PixelFormat.RGBA_8888:
22411c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            case PixelFormat.RGBX_8888:
22511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                estimatedBytePerPixel = 4.0;
22611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                break;
22711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen            default:
22811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                throw new UnsupportedOperationException(
22911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen                        String.format("Invalid format specified %d", format));
23011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen        }
23111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen
23211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen        return (int)(width * height * estimatedBytePerPixel * numImages);
23311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen    }
234bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He
235bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He    private static Size getEffectivePlaneSizeForImage(Image image, int planeIdx) {
236bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He        switch (image.getFormat()) {
237bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.YV12:
238bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.YUV_420_888:
239bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.NV21:
240bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                if (planeIdx == 0) {
241bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                    return new Size(image.getWidth(), image.getHeight());
242bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                } else {
243bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                    return new Size(image.getWidth() / 2, image.getHeight() / 2);
244bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                }
245bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.NV16:
246bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                if (planeIdx == 0) {
247bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                    return new Size(image.getWidth(), image.getHeight());
248bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                } else {
249bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                    return new Size(image.getWidth(), image.getHeight() / 2);
250bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                }
251bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case PixelFormat.RGB_565:
252bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case PixelFormat.RGBA_8888:
253bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case PixelFormat.RGBX_8888:
254bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case PixelFormat.RGB_888:
255bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.JPEG:
256bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.YUY2:
257bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.Y8:
258bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.Y16:
259bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.RAW_SENSOR:
260bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.RAW10:
26144581ff4db54bbaa30365ed210e67a0369576100Yin-Chia Yeh            case ImageFormat.RAW12:
262f7fec7397e37657d08ec6a8c1c214c1f90a77bfdEmilian Peev            case ImageFormat.RAW_DEPTH:
263bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                return new Size(image.getWidth(), image.getHeight());
264bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            case ImageFormat.PRIVATE:
265bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                return new Size(0, 0);
266bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            default:
267bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                throw new UnsupportedOperationException(
268bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He                        String.format("Invalid image format %d", image.getFormat()));
269bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He        }
270bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He    }
271bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He
272bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He    private static void directByteBufferCopy(ByteBuffer srcBuffer, int srcOffset,
273bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He            ByteBuffer dstBuffer, int dstOffset, int srcByteCount) {
274bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He        Memory.memmove(dstBuffer, dstOffset, srcBuffer, srcOffset, srcByteCount);
275bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He    }
276f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He}
277