Skip to content

Instantly share code, notes, and snippets.

@bugparty
Last active February 7, 2017 07:17
Show Gist options
  • Save bugparty/fdf8c259d91cefacbd841584c602072a to your computer and use it in GitHub Desktop.
Save bugparty/fdf8c259d91cefacbd841584c602072a to your computer and use it in GitHub Desktop.
一份yuv转argb代码分析
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