Android下NV21转ARGB的方法
来源:互联网 发布:出售欧美邮箱数据 编辑:程序博客网 时间:2024/05/22 13:28
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<height;iHeight++){for(int iWidth=0;iWidth<width;iWidth++){unsigned char yValue = buffer[width*iHeight+iWidth];int index = iWidth % 2 == 0 ? iWidth : iWidth - 1;unsigned char vValue = buffer[width*height+width*(iHeight/2)+index];unsigned char uValue = buffer[width*height+width*(iHeight/2)+index+1];double r = yValue + (1.370705 * (vValue-128));double g = yValue - (0.698001 * (vValue-128)) - (0.337633 * (uValue-128));double 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);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进行处理了。
0 0
- Android下NV21转ARGB的方法
- YUV转RGB(NV21-ARGB)的Neon优化代码
- YUV转RGB(NV21-ARGB)的Neon优化代码
- jni中 YV12转ARGB 与 NV21转ARGB
- android ARGB 转 RGB
- Color argb()方法的参数
- Android nv21
- android 基于ffmpeg将视频采集的nv21转h264格式数据
- Android系统中Y'UV420p (NV21)到ARGB8888的转换
- 原YUV格式的解析 Android NV21 视频采集
- 原YUV格式的解析 Android NV21 视频采集
- NV21转BGR图像
- Android ARGB 0x
- 【Android】ARGB颜色值
- android 色值设定:ARGB透明度的设置
- ARGB
- ARGB
- ARGB
- Jenkins插件之Publish Over SSH/CIFS/FTP
- Andriod 从源码的角度详解View,ViewGroup的Touch事件的分发机制
- Qt多线程
- DownloadProvider 详细分析
- 目标检测的图像特征提取之(三)Haar特征
- Android下NV21转ARGB的方法
- 关于android OOM整理
- svn(源码仓库)使用导航 ——附svn服务器搭建
- jquery ui和jquery easyui
- 第十三周OJ项目统计元音字母个数
- 安卓市场跳转
- Jenkins Master/Slave架构
- Tuxedo的安装
- 辗转法求最大公约数和最小公倍数