Java 将YUV_420_888转换为字节数组

Java 将YUV_420_888转换为字节数组,java,android,bytearray,camera2,Java,Android,Bytearray,Camera2,我正在测试新的Camera2 API,并且我能够以YUV_420_888格式捕获相机预览。接下来我需要做的是将这些数据提供给图像处理库,该库接受byte[]参数 我已经找到了和这样的例子,但我仍然需要通过ByteArrayOutputStream将生成的位图转换为byte[],这在实验之后会大大降低应用程序的速度 我的问题是,如何有效地将YUV_420_888转换为byte[]呢?图像处理库需要的byte[]数组的实际格式是什么?是RGB吗?是吗?YUV半平面 假设它是RGB,假设您引用了将YU

我正在测试新的Camera2 API,并且我能够以YUV_420_888格式捕获相机预览。接下来我需要做的是将这些数据提供给图像处理库,该库接受byte[]参数

我已经找到了和这样的例子,但我仍然需要通过ByteArrayOutputStream将生成的位图转换为byte[],这在实验之后会大大降低应用程序的速度


我的问题是,如何有效地将YUV_420_888转换为byte[]呢?

图像处理库需要的byte[]数组的实际格式是什么?是RGB吗?是吗?YUV半平面


假设它是RGB,假设您引用了将YUV_420_888转换为RGB,您可以修改该示例,不使用分配创建位图-只使用byte[]而不是位图。

我花了很多时间寻找解决方案,所以我从stackoverflow上其他人的回答中找到了它,我想分享我的自定义代码,它已经针对循环编号进行了优化,它与我一起工作,用于camera2 API:D的YUV420图像

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;
}

抱歉耽搁了。你能给我提供一些关于这个的示例代码吗?我不确定输出字节[]的长度,以及如何初始化输出分配以存储渲染脚本的结果。正如copyTo的文档所述,字节[]的大小至少需要为Allocation.getBytesSize的大小。您引用的示例已经涉及设置输出分配,这不需要任何更改。为了提高效率,您可以使用Allocation.getSurface将输入分配直接连接到camera2 API,请参见以下示例: