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: 60f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case ImageFormat.RAW10: 61f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 1; 62d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He case ImageFormat.PRIVATE: 63f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 0; 64f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He default: 65f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He throw new UnsupportedOperationException( 66f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He String.format("Invalid format specified %d", format)); 67f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 68f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 69f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 70f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He /** 71f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * <p> 72f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * Copy source image data to destination Image. 73f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * </p> 74f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * <p> 75d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * Only support the copy between two non-{@link ImageFormat#PRIVATE PRIVATE} format 76d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * images with same properties (format, size, etc.). The data from the 77d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * source image will be copied to the byteBuffers from the destination Image 78d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * starting from position zero, and the destination image will be rewound to 79d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He * zero after copy is done. 80f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * </p> 81f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * 82f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * @param src The source image to be copied from. 83f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * @param dst The destination image to be copied to. 84f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * @throws IllegalArgumentException If the source and destination images 85f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * have different format, or one of the images is not copyable. 86f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He */ 87f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He public static void imageCopy(Image src, Image dst) { 88f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (src == null || dst == null) { 89f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He throw new IllegalArgumentException("Images should be non-null"); 90f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 91f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (src.getFormat() != dst.getFormat()) { 92f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He throw new IllegalArgumentException("Src and dst images should have the same format"); 93f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 94d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He if (src.getFormat() == ImageFormat.PRIVATE || 95d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He dst.getFormat() == ImageFormat.PRIVATE) { 96d99dc329b9baefe3d722ccafc0c92461cfef42b1Zhijun He throw new IllegalArgumentException("PRIVATE format images are not copyable"); 97f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 98f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (!(dst.getOwner() instanceof ImageWriter)) { 99f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He throw new IllegalArgumentException("Destination image is not from ImageWriter. Only" 100f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He + " the images from ImageWriter are writable"); 101f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 102f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Size srcSize = new Size(src.getWidth(), src.getHeight()); 103f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Size dstSize = new Size(dst.getWidth(), dst.getHeight()); 104f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (!srcSize.equals(dstSize)) { 105f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He throw new IllegalArgumentException("source image size " + srcSize + " is different" 106f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He + " with " + "destination image size " + dstSize); 107f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 108f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 109f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Plane[] srcPlanes = src.getPlanes(); 110f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Plane[] dstPlanes = dst.getPlanes(); 111f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ByteBuffer srcBuffer = null; 112f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ByteBuffer dstBuffer = null; 113f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He for (int i = 0; i < srcPlanes.length; i++) { 114bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He int srcRowStride = srcPlanes[i].getRowStride(); 115bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He int dstRowStride = dstPlanes[i].getRowStride(); 116f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He srcBuffer = srcPlanes[i].getBuffer(); 117bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He dstBuffer = dstPlanes[i].getBuffer(); 118bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He if (!(srcBuffer.isDirect() && dstBuffer.isDirect())) { 119bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He throw new IllegalArgumentException("Source and destination ByteBuffers must be" 120bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He + " direct byteBuffer!"); 121bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 122bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He if (srcPlanes[i].getPixelStride() != dstPlanes[i].getPixelStride()) { 123bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He throw new IllegalArgumentException("Source plane image pixel stride " + 124bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He srcPlanes[i].getPixelStride() + 125bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He " must be same as destination image pixel stride " + 126bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He dstPlanes[i].getPixelStride()); 127bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 128bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He 129f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int srcPos = srcBuffer.position(); 130f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He srcBuffer.rewind(); 131f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dstBuffer.rewind(); 132bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He if (srcRowStride == dstRowStride) { 133bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He // Fast path, just copy the content if the byteBuffer all together. 134bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He dstBuffer.put(srcBuffer); 135bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } else { 136bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He // Source and destination images may have different alignment requirements, 137bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He // therefore may have different strides. Copy row by row for such case. 138bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He int srcOffset = srcBuffer.position(); 139bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He int dstOffset = dstBuffer.position(); 140bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He Size effectivePlaneSize = getEffectivePlaneSizeForImage(src, i); 141bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He int srcByteCount = effectivePlaneSize.getWidth() * srcPlanes[i].getPixelStride(); 142bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He for (int row = 0; row < effectivePlaneSize.getHeight(); row++) { 143bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He if (row == effectivePlaneSize.getHeight() - 1) { 144bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He // Special case for NV21 backed YUV420_888: need handle the last row 145bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He // carefully to avoid memory corruption. Check if we have enough bytes to 146bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He // copy. 147bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He int remainingBytes = srcBuffer.remaining() - srcOffset; 148bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He if (srcByteCount > remainingBytes) { 149bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He srcByteCount = remainingBytes; 150bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 151bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 152bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He directByteBufferCopy(srcBuffer, srcOffset, dstBuffer, dstOffset, srcByteCount); 153bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He srcOffset += srcRowStride; 154bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He dstOffset += dstRowStride; 155bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 156bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 157bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He 158f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He srcBuffer.position(srcPos); 159f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dstBuffer.rewind(); 160f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 161f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 16211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen 16311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen /** 16411c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen * Return the estimated native allocation size in bytes based on width, height, format, 16511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen * and number of images. 16611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen * 16711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen * <p>This is a very rough estimation and should only be used for native allocation 16811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen * registration in VM so it can be accounted for during GC.</p> 16911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen * 17011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen * @param width The width of the images. 17111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen * @param height The height of the images. 17211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen * @param format The format of the images. 17311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen * @param numImages The number of the images. 17411c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen */ 17511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen public static int getEstimatedNativeAllocBytes(int width, int height, int format, 17611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen int numImages) { 17711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen double estimatedBytePerPixel; 17811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen switch (format) { 17911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen // 10x compression from RGB_888 18011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.JPEG: 18111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.DEPTH_POINT_CLOUD: 18211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen estimatedBytePerPixel = 0.3; 18311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen break; 18411c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.Y8: 18511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen estimatedBytePerPixel = 1.0; 18611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen break; 18711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.RAW10: 18811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen estimatedBytePerPixel = 1.25; 18911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen break; 19011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.YV12: 19111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.YUV_420_888: 19211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.NV21: 19311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.PRIVATE: // A really rough estimate because the real size is unknown. 19411c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen estimatedBytePerPixel = 1.5; 19511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen break; 19611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.NV16: 19711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case PixelFormat.RGB_565: 19811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.YUY2: 19911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.Y16: 20011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.RAW_SENSOR: 20111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case ImageFormat.DEPTH16: 20211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen estimatedBytePerPixel = 2.0; 20311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen break; 20411c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case PixelFormat.RGB_888: 20511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen estimatedBytePerPixel = 3.0; 20611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen break; 20711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case PixelFormat.RGBA_8888: 20811c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen case PixelFormat.RGBX_8888: 20911c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen estimatedBytePerPixel = 4.0; 21011c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen break; 21111c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen default: 21211c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen throw new UnsupportedOperationException( 21311c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen String.format("Invalid format specified %d", format)); 21411c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen } 21511c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen 21611c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen return (int)(width * height * estimatedBytePerPixel * numImages); 21711c5d0dd01cccc500796febf63aab404e8ae058bChien-Yu Chen } 218bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He 219bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He private static Size getEffectivePlaneSizeForImage(Image image, int planeIdx) { 220bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He switch (image.getFormat()) { 221bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.YV12: 222bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.YUV_420_888: 223bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.NV21: 224bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He if (planeIdx == 0) { 225bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He return new Size(image.getWidth(), image.getHeight()); 226bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } else { 227bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He return new Size(image.getWidth() / 2, image.getHeight() / 2); 228bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 229bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.NV16: 230bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He if (planeIdx == 0) { 231bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He return new Size(image.getWidth(), image.getHeight()); 232bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } else { 233bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He return new Size(image.getWidth(), image.getHeight() / 2); 234bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 235bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case PixelFormat.RGB_565: 236bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case PixelFormat.RGBA_8888: 237bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case PixelFormat.RGBX_8888: 238bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case PixelFormat.RGB_888: 239bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.JPEG: 240bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.YUY2: 241bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.Y8: 242bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.Y16: 243bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.RAW_SENSOR: 244bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.RAW10: 245bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He return new Size(image.getWidth(), image.getHeight()); 246bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He case ImageFormat.PRIVATE: 247bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He return new Size(0, 0); 248bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He default: 249bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He throw new UnsupportedOperationException( 250bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He String.format("Invalid image format %d", image.getFormat())); 251bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 252bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 253bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He 254bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He private static void directByteBufferCopy(ByteBuffer srcBuffer, int srcOffset, 255bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He ByteBuffer dstBuffer, int dstOffset, int srcByteCount) { 256bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He Memory.memmove(dstBuffer, dstOffset, srcBuffer, srcOffset, srcByteCount); 257bc0b63667960896929fdfcc0d95491ff8f1ef00aZhijun He } 258f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 259