It’s now or never

IT系の技術ブログです。気になったこと、勉強したことを備忘録的にまとめて行きます。

UIImageから生の画像データを取得/RGBデータからYUVデータへ変換

下記のようなソースで、画像ファイルからUIImageオブジェクトに読み込んだ画像の ビットマップデータを取得することができます。

CGImageRef newCgImage           = [UIImage imageNamed:@"pingFile"].CGImage;
CGDataProviderRef dataProvider = CGImageGetDataProvider(newCgImage);
CFDataRef bitmapData            = CGDataProviderCopyData(dataProvider);
uint8_t *buff                   = (uint8_t *)CFDataGetBytePtr(bitmapData);

RGBデータからYUVデータへ変換する

上記、UIImageのソースで取得したデータは、RGBAのビットマップデータとなっていますが、 用途によっては、YUVデータとして扱いたいこともあると思います。

その場合は、次のように変換が可能です。

/**
 *  rgva形式からyuv形式へ変換
 */
rgba_to_yuv(unsigned char *in_rgba, unsigned char *out_yuv, unsigned int w, unsigned int h)
{
    unsigned int x;
    unsigned int y;
    
    for(y = 0; y < h; y++) {
        for(x = 0; x < w; x++) {
            png_byte r;
            png_byte g;
            png_byte b;
            
            // 4バイトずつ読み込みalphaは無視する
            r = in_rgba[4 * (x + w * y) + 0];
            g = in_rgba[4 * (x + w * y) + 1];
            b = in_rgba[4 * (x + w * y) + 2];
            
            /* XXX: Cringe. */
            out_yuv[3 * (x + w * y) + 0] = clamp(
                                             0.299 * r
                                             + 0.587 * g
                                             + 0.114 * b);
            out_yuv[3 * (x + w * y) + 1] = clamp((0.436 * 255
                                              - 0.14713 * r
                                              - 0.28886 * g
                                              + 0.436 * b) / 0.872);
            out_yuv[3 * (x + w * y) + 2] = clamp((0.615 * 255
                                              + 0.615 * r
                                              - 0.51499 * g
                                              - 0.10001 * b) / 1.230);
        }
    }
}

unsigned char clamp(double d)
{
    if(d < 0)
        return 0;
    
    if(d > 255)
        return 255;
    
    return d;
}

変換の式などは、調べるとすぐに出てきますが、 詳しい仕様などは理解できていません。。

また、今回取得したビットマップの形式がrgbaだったため、4バイトづつ変換していますが、 おそらくrgbでも取得できるはずです。

機会があれば、その辺を踏まえて画像のフィルタなども扱ってみようと思います。

画像もまた奥が深いです。