YUVフォーマットからRGBフォーマットへの変換|C言語
C言語でYUVフォーマットからRGBフォーマットに変換するサンプルです。
共通処理
最大値・最小値設定マクロ
#define max(A, B) ((A) > (B) ? (A) : (B))
#define min(A, B) ((A) < (B) ? (A) : (B))
YUV値からRGBのバイト列を作成
変換式は以下になります。
R = ((Y-16)/219 + 1.402*(Cr-128)/224) * 255
G = ((Y-16)/219 - 0.344*(Cb-128)/224 - 0.714*(Cr-128)/224) * 255
B = ((Y-16)/219 + 1.772*(Cb-128)/224) * 255
static void
_yuv2rgb(int y, int cb, int cr, jbyte* rgb)
{
// 変換式
// R = ((Y-16)/219 + 1.402*(Cr-128)/224) * 255
// G = ((Y-16)/219 - 0.344*(Cb-128)/224 - 0.714*(Cr-128)/224) * 255
// B = ((Y-16)/219 + 1.772*(Cb-128)/224) * 255
y = y - 16;
cr -= 128;
cb -= 128;
int r, g, b;
r = 1164 * y + 1596 * cr;
g = 1164 * y - 392 * cb - 813 * cr;
b = 1164 * y + 2017 * cb;
rgb[0] = (jbyte)min(max(r, 999) / 1000, 255);
rgb[1] = (jbyte)min(max(g, 999) / 1000, 255);
rgb[2] = (jbyte)min(max(b, 999) / 1000, 255);
}
1164 = 255 / 291 * 1000
その他も同様に計算した結果の値です。
上記で1000倍しているため、各値格納時に1/1000にします。
YUV420SP(YVU420SP)からの変換
static jbyte*
_yuvsp2rgb(int width, int height, jbyte * ybytes, jbyte * ubytes, jbyte * vbytes,
int ystride, int ustride, int vstride)
{
// 総ピクセル数
long length = width * height * 3;
jbyte * rgb = (jbyte*) malloc(sizeof(jbyte) * length);
int w, h;
int y, u, v;
int isUV = (ubytes < vbytes) ? 1 : 0;
jbyte * p_y = ybytes;
jbyte * p_u;
jbyte * p_v;
if (isUV == 1) {
p_u = ubytes;
p_v = p_u + 1;
} else {
p_v = vbytes;
p_u = p_v + 1;
}
int index = 0;
jbyte rgbPixel[3];
for (h = 0; h < height; h++) {
if (0 < h) {
p_y += ystride;
if ((h & 1) == 0) {
if (isUV == 1) {
p_u += ustride;
p_v = p_u + 1;
} else {
p_v += vstride;
p_u = p_v + 1;
}
}
}
for (w = 0; w < width; w++) {
y = 0xff & p_y[w];
if ((w & 1) == 0) {
v = 0xff & p_v[w];
u = 0xff & p_u[w];
}
_yuv2rgb(y, u, v, rgbPixel);
rgb[index++] = rgbPixel[0];
rgb[index++] = rgbPixel[1];
rgb[index++] = rgbPixel[2];
}
}
return rgb;
}
YUV420Pからの変換
static jbyte*
_yuvp2rgb(int width, int height, jbyte * ybytes, jbyte * ubytes, jbyte * vbytes,
int ystride, int ustride, int vstride)
{
// 総ピクセル数
long length = width * height * 3;
jbyte * rgb = (jbyte*) malloc(sizeof(jbyte) * length);
int w, h;
int y, u, v;
jbyte * p_y = ybytes;
jbyte * p_u = ubytes;
jbyte * p_v = vbytes;
int index = 0;
jbyte rgbPixel[3];
for (h = 0; h < height; h++) {
if (0 < h) {
p_y += ystride;
if ((h & 1) == 0) {
p_u += ustride;
p_v += vstride;
}
}
for (w = 0; w < width; w++) {
y = 0xff & p_y[w];
v = 0xff & p_v[w / 2];
u = 0xff & p_u[w / 2];
_yuv2rgb(y, u, v, rgbPixel);
rgb[index++] = rgbPixel[0];
rgb[index++] = rgbPixel[1];
rgb[index++] = rgbPixel[2];
}
}
return rgb;
}