Last active
February 7, 2017 07:17
-
-
Save bugparty/fdf8c259d91cefacbd841584c602072a to your computer and use it in GitHub Desktop.
一份yuv转argb代码分析
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
JNIEXPORT void JNICALL Java_jp_co_cyberagent_android_gpuimage_GPUImageNativeLibrary_YUVtoARBG(JNIEnv * env, jobject obj, jbyteArray yuv420sp, jint width, jint height, jintArray rgbOut) | |
{ | |
int sz; | |
int i; | |
int j; | |
int Y; | |
int Cr = 0; | |
int Cb = 0; | |
int pixPtr = 0; | |
int jDiv2 = 0; | |
int R = 0; | |
int G = 0; | |
int B = 0; | |
int cOff; | |
int w = width; | |
int h = height; | |
/*数据格式为yuv420sp(NV21) | |
ex: YYYYYYYYUVUV | |
即8个Y值排在一起,UV交错排列, 每四个Y共用一对UV | |
+-----+-----+-----+-----+ | |
| Y0 | Y1 | Y2 | Y3 | | |
+-----+-----+-----+-----+ | |
| Y4 | Y5 | Y6 | Y7 | | |
+-----+-----+-----+-----+ | |
| Y8 | Y9 | Y10 | Y11 | | |
+-----+-----+-----+-----+ | |
| Y12 | Y13 | Y14 | Y15 | | |
+-----+-----+-----+-----+ | |
| U0 | V0 | U1 | V1 | | |
+-----+-----+-----+-----+ | |
| U2 | V2 | U3 | V3 | | |
+-----+-----+-----+-----+ | |
*/ | |
sz = w * h;//Y的数据大小 ,用于定位UV的首地址, Y的数据量始终等于图像的宽乘以高 | |
jint *rgbData = (jint*) ((*env)->GetPrimitiveArrayCritical(env, rgbOut, 0)); | |
jbyte* yuv = (jbyte*) (*env)->GetPrimitiveArrayCritical(env, yuv420sp, 0); | |
for(j = 0; j < h; j++) { //逐行处理 | |
pixPtr = j * w; | |
jDiv2 = j >> 1; | |
for(i = 0; i < w; i++) { | |
Y = yuv[pixPtr]; | |
if(Y < 0) Y += 255; | |
//i & 0x1) != 1 用于快速判断是不是偶数的trick | |
//含义是只在x坐标为偶数时计算Cb,Cr,也就是说 | |
if((i & 0x1) != 1) { //逐个像素处理 | |
//UV的矩阵的宽和高是Y矩阵的一半大小 | |
//所以每个像素对应的UV值坐标是(j/2,i/2) | |
// (i>>2)*2 是去掉最低位1的trick,把数字转换为偶数 | |
cOff = sz + jDiv2 * w + (i >> 1) * 2; | |
Cb = yuv[cOff]; | |
if(Cb < 0) Cb += 127; else Cb -= 128; | |
Cr = yuv[cOff + 1]; | |
if(Cr < 0) Cr += 127; else Cr -= 128; | |
} | |
//ITU-R BT.601 conversion | |
// | |
//R = 1.164*(Y-16) + 2.018*(Cr-128); | |
//G = 1.164*(Y-16) - 0.813*(Cb-128) - 0.391*(Cr-128); | |
//B = 1.164*(Y-16) + 1.596*(Cb-128); | |
// | |
Y = Y + (Y >> 3) + (Y >> 5) + (Y >> 7); | |
R = Y + (Cr << 1) + (Cr >> 6); | |
if(R < 0) R = 0; else if(R > 255) R = 255; | |
G = Y - Cb + (Cb >> 3) + (Cb >> 4) - (Cr >> 1) + (Cr >> 3); | |
if(G < 0) G = 0; else if(G > 255) G = 255; | |
B = Y + Cb + (Cb >> 1) + (Cb >> 4) + (Cb >> 5); | |
if(B < 0) B = 0; else if(B > 255) B = 255; | |
rgbData[pixPtr++] = 0xff000000 + (B << 16) + (G << 8) + R; | |
} | |
} | |
(*env)->ReleasePrimitiveArrayCritical(env, rgbOut, rgbData, 0); | |
(*env)->ReleasePrimitiveArrayCritical(env, yuv420sp, yuv, 0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment