有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java将YUV_420_888转换为字节数组

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

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

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


共 (2) 个答案

  1. # 1 楼答案

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

    假设它是RGB,假设您引用了将YUV_420_888转换为RGB,您可以修改该示例以不从分配创建位图-只需使用带字节[]的Allocation.copyTo而不是位图

  2. # 2 楼答案

    我花了很多时间寻找解决方案,所以我从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;
    }