如何转换YUV_420_888到YUV422(UYVY)

时间:2019-03-28 07:00:17

标签: android image android-camera2 yuv

您知道,我们可以从Android Camera2 API(ImageReader.OnImageAvailableListener)获取图像,图像格式为YUV_420_888,我需要将格式转换为YUV422(UYVY)。

有关相机图像的信息。

从3个平面获取数据

pixelStride 1
rowStride 720
width 720
height 480
buffer size 345600

从平面0读取数据完成

pixelStride 2
rowStride 720
width 720
height 480
buffer size 172799

从平面1读取数据完成

pixelStride 2
rowStride 720
width 720
height 480
buffer size 172799

从平面2读取数据完成

我的转换函数如下,

private static byte[] getDataFromImage(Image image, int colorFormat) {
    if (colorFormat != COLOR_FormatI420 && colorFormat != COLOR_FormatNV21 && colorFormat != COLOR_FormatYUYV422_UYVY) {
        throw new IllegalArgumentException("only support COLOR_FormatI420 " + "and COLOR_FormatNV21"  + "and COLOR_FormatYUYV422_UYVY");
    }
    if (!isImageFormatSupported(image)) {
        throw new RuntimeException("can't convert Image to byte array, format " + image.getFormat());
    }
    Rect crop = image.getCropRect();
    int format = image.getFormat();
    int width = crop.width();
    int height = crop.height();
    Image.Plane[] planes = image.getPlanes();
    byte[] data = new byte[width * height * 2];
    byte[] rowData = new byte[planes[0].getRowStride()];
    Log.e(TAG, "get data from " + planes.length + " planes" + "format is " + format);
    int channelOffset = 0;
    int outputStride = 1;
    for (int i = 0; i < planes.length; i++) {
        switch (i) {
            case 0:
                if(false) {
                    channelOffset = 0;
                    outputStride = 1;
                } else { //for YUV422 UYVY
                    channelOffset = 1;
                    outputStride = 2;
                }
                break;
            case 1:
                if (colorFormat == COLOR_FormatI420) {
                    channelOffset = width * height;
                    outputStride = 1;
                } else if (colorFormat == COLOR_FormatNV21) {
                    channelOffset = width * height + 1;
                    outputStride = 2;
                } else { //for YUV422 UYVY
                    channelOffset = 0;
                    outputStride = 4;
                }
                break;
            case 2:
                if (colorFormat == COLOR_FormatI420) {
                    channelOffset = (int) (width * height * 1.25);
                    outputStride = 1;
                } else if (colorFormat == COLOR_FormatNV21) {
                    channelOffset = width * height;
                    outputStride = 2;
                } else { //for YUV422 UYVY
                    channelOffset = 2;
                    outputStride = 4;
                }
                break;
        }
        ByteBuffer buffer = planes[i].getBuffer();
        int rowStride = planes[i].getRowStride();
        int pixelStride = planes[i].getPixelStride();
        Log.e(TAG, "pixelStride " + pixelStride);
        Log.e(TAG, "rowStride " + rowStride);
        Log.e(TAG, "width " + width);
        Log.e(TAG, "height " + height);
        Log.e(TAG, "buffer size " + buffer.remaining());
        int shift = (i == 0) ? 0 : 1;
        int w = width; // >> shift;
        int h = height;// >> shift;
        buffer.position(rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift));
        Log.e(TAG, "buffer position " + buffer.position());
        for (int row = 0; row < h; row++) {
            int length;
            if (pixelStride == 1 && outputStride == 1) {
                length = w;
                buffer.get(data, channelOffset, length);
                channelOffset += length;
            } else {
                if (i == 0) {
                    length = w;
                    buffer.get(rowData, 0, length);
                } else {
                    if(row == h - 2) {
                        length = w - 1;
                    } else {
                        length = w;
                    }
                    if( row % 2 == 0) {
                       // Log.e(TAG, "row is " + row + "length " + length);
                        buffer.get(rowData, 0, length);
                    }
                }

                if(colorFormat != COLOR_FormatYUYV422_UYVY) {
                    for (int col = 0; col < w; col++) {
                        data[channelOffset] = rowData[col * pixelStride];
                        channelOffset += outputStride;
                    }
                } else {
                    if(i == 0) {
                        for (int col = 0; col < w; col++) {
                            data[channelOffset] = rowData[col * pixelStride];
                            channelOffset += outputStride;
                        }
                    } else {
                        for (int col = 0; col < w-1;) {
                            data[channelOffset] = rowData[col];
                            col = col + 2;
                            channelOffset += outputStride;
                        }
                    }
                }
            }
//                if (row < h - 1) {
//                    buffer.position(buffer.position() + rowStride - length);
//                }
        }
        Log.e(TAG, "Finished reading data from plane " + i);
    }
    Log.e(TAG, "data length is " + data.length);
    return data;
}

当我将第二个参数colorFormat设置为COLOR_FormatYUYV422_UYVY时, 函数getDataFromImage是将YUV420_888转换为YUV422_UYVY的响应。 但是,图像的颜色不正确。 谁可以查看用于转换的功能getDataFromImage(YUV420_888-> YUV422(UYVY))?

0 个答案:

没有答案