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;
}
このエントリーをはてなブックマークに追加
にほんブログ村 IT技術ブログへ

コメント

メールアドレスが公開されることはありません。 が付いている欄は必須項目です