1

I am testing out the new Camera2 API, and I'm able to capture the camera preview in YUV_420_888 format. What I need to do next is to feed this data to a image processing library, which accepts a byte[] parameter.

I've found examples of converting YUV_420_888 to RGB and such, but I still need to convert the resulting Bitmap to byte[] through ByteArrayOutputStream, which after experimenting, is slowing down the app tremendously.

My question is, how do I convert YUV_420_888 to byte[] efficiently?

Community
  • 1
  • 1
tropicalfish
  • 1,230
  • 1
  • 16
  • 29

2 Answers2

0

What is the actual format of the byte[] array the image processing library wants? Is it RGB? YUV planar? YUV semiplanar?

Assuming it's RGB, given that you reference converting YUV_420_888 to RGB, you can just modify that example to not create a Bitmap from the allocation - just use Allocation.copyTo with byte[] instead of Bitmap.

Eddy Talvala
  • 17,243
  • 2
  • 42
  • 47
  • apologize for the delay. Would you be able to provide me some sample code on this? I am not sure what's the length of the output `byte[]`, and how should i initialise the output `Allocation`to store the result from the render script. – tropicalfish Sep 02 '16 at 05:15
  • As the documentation for copyTo says, the byte[] needs to be at least the size of Allocation.getBytesSize (https://developer.android.com/reference/android/renderscript/Allocation.html#getBytesSize()). The example you reference already deals with setting up the output Allocation, that won't need any changes. For even more efficiency, you could connect the input Allocation directly to the camera2 API with Allocation.getSurface (https://developer.android.com/reference/android/renderscript/Allocation.html#getSurface()), see this example: https://github.com/googlesamples/android-HdrViewfinder – Eddy Talvala Sep 06 '16 at 20:57
0

I've take a lot of time for looking a solution, so i found it, from answer of other guy on stackoverflow, i want share my customize code which has been optimized for loop numbers, it work with me, for YUV420 Image of camera2 API :D

public static byte[] imageToMat(Image image) {

    Image.Plane[] planes = image.getPlanes();

    ByteBuffer buffer0 = planes[0].getBuffer();
    ByteBuffer buffer1 = planes[1].getBuffer();
    ByteBuffer buffer2 = planes[2].getBuffer();

    int offset = 0;

    int width = image.getWidth();
    int height = image.getHeight();

    byte[] data = new byte[image.getWidth() * image.getHeight() * ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8];
    byte[] rowData1 = new byte[planes[1].getRowStride()];
    byte[] rowData2 = new byte[planes[2].getRowStride()];

    int bytesPerPixel = ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8;

    // loop via rows of u/v channels

    int offsetY = 0;

    int sizeY =  width * height * bytesPerPixel;
    int sizeUV = (width * height * bytesPerPixel) / 4;

    for (int row = 0; row < height ; row++) {

        // fill data for Y channel, two row
        {
            int length = bytesPerPixel * width;
            buffer0.get(data, offsetY, length);

            if ( height - row != 1)
                buffer0.position(buffer0.position()  +  planes[0].getRowStride() - length);

            offsetY += length;
        }

        if (row >= height/2)
            continue;

        {
            int uvlength = planes[1].getRowStride();

            if ( (height / 2 - row) == 1 ) {
                uvlength = width / 2 - planes[1].getPixelStride() + 1;
            }

            buffer1.get(rowData1, 0, uvlength);
            buffer2.get(rowData2, 0, uvlength);

            // fill data for u/v channels
            for (int col = 0; col < width / 2; ++col) {
                // u channel
                data[sizeY + (row * width)/2 + col] = rowData1[col * planes[1].getPixelStride()];

                // v channel
                data[sizeY + sizeUV + (row * width)/2 + col] = rowData2[col * planes[2].getPixelStride()];
            }
        }

    }

    return data;
}
  • It works for me. I am using ImageReader from Camera2 + Zoom Video SDK and this is the solution that allowed me to see the image in color – Deneb Chorny Apr 25 '22 at 18:11