Android系统中Y'UV420p (NV21)到ARGB8888的转换

http://en.wikipedia.org/wiki/YUV

This format (NV21) is the standard picture format on android camera preview. YUV 4:2:0 planar image, with 8 bit Y samples, followed by interleaved V/U plane with 8bit 2x2 subsampled chroma samples.[8]

Java source code used on Android:

但是NV21在Microsoft中的定义是:

Microsoft defines this format as follows:

 "The same as NV12, except that Cb and Cr samples are swapped so that the chroma array of unsigned char would have Cr followed by Cb for each sample (such that if addressed as a little-endian WORD type, Cr would be in the LSBs and Cb would be in the MSBs)."

参考: http://www.fourcc.org/yuv.php

/**
 * Converts YUV420 NV21 to ARGB8888
 * 
 * @param data byte array on YUV420 NV21 format.
 * @param width pixels width
 * @param height pixels height
 * @return a ARGB8888 pixels int array. Where each int is a pixels ARGB. 
 */
public static int[] convertYUV420_NV21toARGB8888(byte [] data, int width, int height) {
    int size = width*height;
    int offset = size;
    int[] pixels = new int[size];
    int u, v, y1, y2, y3, y4;
 
    // i along Y and the final pixels
    // k along pixels U and V
    for(int i=0, k=0; i < size; i+=2, k+=2) {
        y1 = data[i  ]&0xff;
        y2 = data[i+1]&0xff;
        y3 = data[width+i  ]&0xff;
        y4 = data[width+i+1]&0xff;
 
        u = data[offset+k  ]&0xff;
        v = data[offset+k+1]&0xff;
        u = u-128;
        v = v-128;
 
        pixels[i  ] = convertYUVtoARGB(y1, u, v);
        pixels[i+1] = convertYUVtoARGB(y2, u, v);
        pixels[width+i  ] = convertYUVtoARGB(y3, u, v);
        pixels[width+i+1] = convertYUVtoARGB(y4, u, v);
 
        if (i!=0 && (i+2)%width==0)
            i+=width;
    }
 
    return pixels;
}
 
private static int convertYUVtoARGB(int y, int u, int v) {
    int r,g,b;
 
    r = y + (int)1.402f*u;
    g = y - (int)(0.344f*v +0.714f*u);
    b = y + (int)1.772f*v;
    r = r>255? 255 : r<0 ? 0 : r;
    g = g>255? 255 : g<0 ? 0 : g;
    b = b>255? 255 : b<0 ? 0 : b;
    return 0xff000000 | (r<<16) | (g<<8) | b;
}


 

 

http://stackoverflow.com/questions/16737749/onpreviewframe-yuv-grayscale-skewed

http://stackoverflow.com/questions/8340128/decoding-yuv-to-rgb-in-c-c-with-ndk

http://msdn.microsoft.com/zh-cn/library/windowsphone/develop/microsoft.devices.photocamera.ycbcrpixellayout(v=vs.105).aspx

 

在Android API Level-9中YUV格式采用YV12(YVU420)格式,而且若Y分量的宽度不是16的整倍数时,进行扩展。但是Y分量的高是奇数时,U,V分量的高是hight/2

http://stackoverflow.com/questions/16737749/onpreviewframe-yuv-grayscale-skewed

public static final int YV12

Added in API level 9 Android YUV format.

This format is exposed to software decoders and applications.

YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed by (W/2) x (H/2) Cr and Cb planes.

This format assumes

an even width an even height a horizontal stride multiple of 16 pixels a vertical stride equal to the height y_size = stride * height c_stride = ALIGN(stride/2, 16) c_size = c_stride * height/2 size = y_size + c_size * 2 cr_offset = y_size cb_offset = y_size + c_size

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,针对您的问题,我可以提供以下的参考代码,可以将 Android camera2 api YUV_420_888 格式的数据转换RGB 格式的数据: ``` private void convertYUV420ToRGB(Image imgYUV, Bitmap imgRGB) { // Get image width and height int width = imgYUV.getWidth(); int height = imgYUV.getHeight(); // Get Y, U, and V image planes from image Image.Plane[] planes = imgYUV.getPlanes(); ByteBuffer bufferY = planes[0].getBuffer(); ByteBuffer bufferU = planes[1].getBuffer(); ByteBuffer bufferV = planes[2].getBuffer(); // Calculate pixel stride and row stride for Y, U, and V image planes int pixelStrideY = planes[0].getPixelStride(); int rowStrideY = planes[0].getRowStride(); int pixelStrideU = planes[1].getPixelStride(); int rowStrideU = planes[1].getRowStride(); int pixelStrideV = planes[2].getPixelStride(); int rowStrideV = planes[2].getRowStride(); // Create arrays for storing pixel data byte[] dataY = new byte[width * height * pixelStrideY]; byte[] dataU = new byte[width * height * pixelStrideU / 4]; byte[] dataV = new byte[width * height * pixelStrideV / 4]; // Copy pixel data from image planes into arrays bufferY.get(dataY, 0, width * height * pixelStrideY); bufferU.get(dataU, 0, width * height * pixelStrideU / 4); bufferV.get(dataV, 0, width * height * pixelStrideV / 4); // Initialize RGB pixel buffer int[] pixels = new int[width * height]; int offset = 0; // Loop through each row and column of pixels for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Get YUV pixel values for current pixel int Y = dataY[offset] & 0xff; int U = dataU[offset / 4] & 0xff; int V = dataV[offset / 4] & 0xff; // Calculate RGB pixel values for current pixel int R = (int)(Y + 1.370705f * (V - 128)); int G = (int)(Y - 0.698001f * (V - 128) - 0.337633f * (U - 128)); int B = (int)(Y + 1.732446f * (U - 128)); // Clip RGB pixel values to range [0, 255] R = Math.max(0, Math.min(255, R)); G = Math.max(0, Math.min(255, G)); B = Math.max(0, Math.min(255, B)); // Combine RGB pixel values into single pixel pixels[offset++] = (0xff << 24) | (R << 16) | (G << 8) | B; } // Move to next row of pixels offset += rowStrideY - width * pixelStrideY; } // Set RGB pixel data into Bitmap imgRGB.setPixels(pixels, 0, width, 0, 0, width, height); } ``` 这个方法将会把 Image 对象 imgYUV YUV 数据转换RGB 数据,并且将其存储到 Bitmap 对象 imgRGB 。其YUV 数据的格式为 YUV_420_888,RGB 数据的格式为 ARGB_8888。 注意,这个方法转换公式是基于 YUV420 的格式,如果您的 YUV 数据格式不同,需要根据实际情况对转换公式进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值