Android Camera.PreviewCallback回来的每一帧图像的格式为NV21,NV21是YUV420的一种。但具体YUV三个分量怎么存储,Android的文档没有指出。在网上找了很多,都没有详细的介绍,其中曲折就不说了。最终在这里找到了权威的介绍:

http://www.fourcc.org/yuv.php#NV12
将其摘要如下:
NV12YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved U/V plane containing 8 bit 2x2 subsampled colour difference samples.                   HorizontalVerticalY Sample Period               11V (Cr) Sample Period           22U (Cb) Sample Period           22Microsoft defines this format as follows: "A format in which all Y samples are found first in memory as an array of unsigned char with an even number of lines (possibly with a larger stride for memory alignment), followed immediately by an array of unsigned char containing interleaved Cb and Cr samples (such that if addressed as a little-endian WORD type, Cb would be in the LSBs and Cr would be in the MSBs) with the same total stride as the Y samples.This is the preferred 4:2:0 pixel format."NV21YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved V/U plane containing 8 bit 2x2 subsampled chroma samples. The same as NV12 except the interleave order of U and V is reversed.                   HorizontalVerticalY Sample Period                11V (Cr) Sample Period           22U (Cb) Sample Period           22Microsoft 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)."

意思就是NV21是按YUV 4:2:0抽样的。即,对于一张图片的每一个像素,完整保留其Y分量,而对于U和V分量,以2X2的像素块比例采样。其中Y分量按平面存储,U和V则交错打包存储。NV12和NV21都是Y分量在前,U和V分量打包在后。不同处在于NV12是按UV顺序打包,而NV21是按VU顺序打包的。

了解了NV21的YUV存储顺序后,再加上YUV转RGB的公式就OK了。

 YUV转RGB的公式,网上也是一大堆,最终我在Wikipedia上找到了一个可以用的公式,先附上Wikipedia的连接:

http://en.wikipedia.org/wiki/YUV#Y.27UV420sp_.28NV21.29_to_RGB_conversion_.28Android.29
其摘要如下:
void YUVImage::yuv2rgb(uint8_t yValue, uint8_t uValue, uint8_t vValue,        uint8_t *r, uint8_t *g, uint8_t *b) const {    *r = yValue + (1.370705 * (vValue-128));    *g = yValue - (0.698001 * (vValue-128)) - (0.337633 * (uValue-128));    *b = yValue + (1.732446 * (uValue-128));    *r = clamp(*r, 0, 255);    *g = clamp(*g, 0, 255);    *b = clamp(*b, 0, 255);}
   

稍微简化一下,即:

    r = yValue + (1.370705 * (vValue-128));    g = yValue - (0.698001 * (vValue-128)) - (0.337633 * (uValue-128));    b = yValue + (1.732446 * (uValue-128));    r = r < 0 ? 0 : ( r > 255 ? 255 : r);    g = g < 0 ? 0 : ( g > 255 ? 255 : g);    b = b < 0 ? 0 : ( b > 255 ? 255 : b);

到此,NV21转RGB的算法已经一目了然了,即,对于每一个像素,取出其对应的YUV的值,然后,算出该像素对应的RGB的值即可。

下面是我在Android下JNI层的转换代码:

jboolean copy = 1;unsigned char *buffer = (unsigned char*)env->GetByteArrayElements(data,©);int length = width*height*4;unsigned char *rgbBuf = (unsigned char*)malloc(length);for(int iHeight = 0;iHeight 255 ? 255 : r);g = g < 0 ? 0 : ( g > 255 ? 255 : g);b = b < 0 ? 0 : ( b > 255 ? 255 : b);rgbBuf[width*iHeight*4+iWidth*4+0] = (unsigned char)r;rgbBuf[width*iHeight*4+iWidth*4+1] = (unsigned char)g;rgbBuf[width*iHeight*4+iWidth*4+2] = (unsigned char)b;rgbBuf[width*iHeight*4+iWidth*4+3] = 255;}}env->ReleaseByteArrayElements(data,(jbyte*)buffer,0);jbyteArray arr = env->NewByteArray(length);jbyte *buf = (jbyte*)malloc(length);memcpy(buf,rgbBuf,length);env->SetByteArrayRegion(arr,0,length,buf);free(buf);free(rgbBuf);return arr;

其中 data,width,height分别为Java层传入参数。env为JNI层默认带的参数。最终返回的arr为jbyteArray类型,到了Java层即byte[].注意这里我的像素通道顺序是RGBA.这样,到了Java层,其返回的byte[]中的顺序就是ARGB了,然后就可以按照ARGB_8888进行处理了。

更多相关文章

  1. Android 获取摄像头像素,个数
  2. Android编译系统中头文件搜索路径顺序的一个问题
  3. 入门:Android 文档的阅读顺序
  4. android 模拟器对应像素
  5. Android 实现多个Audio文件的顺序播放
  6. Android Service启动执行顺序
  7. OpenCV 的 RGB 顺序和 Android 载入的 RGB 顺序相反
  8. android 字体大小像素的设置
  9. android 字体大小,样式 ,像素的设置

随机推荐

  1. Android(安卓)SeekBar控件
  2. android 使用webview加载网页问题
  3. android so壳入口浅析
  4. [Android(安卓)Training视频系列] 6.2 Sa
  5. android开玩笑之创建xml文件
  6. 创建一个android项目与创建一个android虚
  7. Android中Rect和RectF的区别与联系
  8. Android入门第十二篇之Gallery[转]
  9. Android(安卓)常见错误处理
  10. android中Drawable总结