Introduction to Audio and Video-08-RGB&YUV

Keywords: C++ Mobile

Directory of introductory audio and video articles

YUV & RGB reciprocal conversion formula

YCbCr Y has the same meaning as Y in Y UV. Cb and CR both refer to color. Cb refers to blue color and Cr refers to red color. YCbCr Y is widely used in JPEG, MPEG, DVD, camera, digital TV and so on.
Therefore, the general term YUV mostly refers to YCbCr.

  • RGB to YUV(YCbCr)

RGB range [0,255], Y range [16,235], UV range [16,239].Intercept results if they exceed the range.

Y = 0.257*R + 0.504*G + 0.098*B + 16;
U = -0.148*R - 0.291*G + 0.439*B + 128;
V = 0.439*R - 0.368*G - 0.071*B + 128;
  • YUV(YCbCr)to RGB

RGB range [0,255], Y range [16,235], UV range [16,239].Intercept results if they exceed the range.

R = 1.164*(Y - 16) + 1.596*(V - 128);
G = 1.164*(Y - 16) - 0.813*(V - 128) - 0.391*(U - 128);
B = 1.164*(Y - 16) + 2.018*(U - 128);

Assistance to FFmpeg tool

FFmpeg will Previously generated rainbow graph BMP Files converted to YUV format, RGB format

ffmpeg -i rainbow.bmp -video_size 700x700 -pix_fmt yuv444p rainbow-yuv444p.yuv
ffmpeg -i rainbow.bmp -video_size 700x700 -pix_fmt rgb24 rainbow-rgb24.rgb

FFplay View the resulting YUV, RGB files

ffplay -f rawvideo -pix_fmt yuv444p -video_size 700x700 rainbow-yuv444p.yuv
ffplay -f rawvideo -pix_fmt rgb24 -video_size 700x700 rainbow-rgb24.rgb

RGB & YUV Conversion by Code

RGB -> YUV

Convert the RGB24 format generated by FFmpeg to YUV444P format.
[rainbow-rgb24.rgb] -> [rainbow-rgb24-to-yuv444p.yuv]

#include <stdio.h>
#include <string.h>
#include <math.h>

// Seven Colors of Rainbow
u_int32_t rainbowColors[] = {
        0XFF0000, // red
        0XFFA500, // orange
        0XFFFF00, // yellow
        0X00FF00, // green
        0X007FFF, // young
        0X0000FF, // blue
        0X8B00FF  // purple
};

u_int8_t bound(u_int8_t start, int value, u_int8_t end) {
    if(value <= start) {
        return start;
    }
    if(value >= end) {
        return end;
    }
    return value;
}

void rgbToYuv(u_int8_t R, u_int8_t G, u_int8_t B, u_int8_t *Y, u_int8_t *U, u_int8_t *V) {
    int y_val = (int)round(0.257*R + 0.504*G + 0.098*B + 16);
    int u_val = (int)round(-0.148*R - 0.291*G + 0.439*B + 128);
    int v_val = (int)round(0.439*R - 0.368*G - 0.071*B + 128);
    *Y = bound(16, y_val, 235);
    *U = bound(16, u_val, 239);
    *V = bound(16, v_val, 239);
}


void rgb24ToYuv444p(const u_int8_t *rgb24Data, u_int8_t *yuv444pData, int width, int height) {

    int8_t yuv_y[width*height];
    int8_t yuv_u[width*height];
    int8_t yuv_v[width*height];

    for (int i = 0; i < width; ++i) {
        for (int j = 0; j < height; ++j) {
            u_int8_t Y, U, V;
            u_int8_t R, G, B;

            int currentRGBIndex = 3*(i*height+j);
            R = rgb24Data[currentRGBIndex];
            G = rgb24Data[currentRGBIndex+1];
            B = rgb24Data[currentRGBIndex+2];

            rgbToYuv(R, G, B, &Y, &U, &V);

            int currentYUVIndex = i*height+j;
            yuv_y[currentYUVIndex] = Y;
            yuv_u[currentYUVIndex] = U;
            yuv_v[currentYUVIndex] = V;
        }
    }
    
    memcpy(yuv444pData, yuv_y, sizeof(yuv_y));
    memcpy(yuv444pData + sizeof(yuv_y), yuv_u, sizeof(yuv_u));
    memcpy(yuv444pData + sizeof(yuv_y) + sizeof(yuv_u), yuv_v, sizeof(yuv_v));
    
}

int main() {
    int width = 700, height = 700;
    u_int8_t yuv444pData[width*height*3];
    u_int8_t rgb24Data[width*height*3];
    
    FILE *rgb24File = fopen("/Users/staff/Desktop/rainbow-rgb24.rgb", "rb");
    fread(rgb24Data, sizeof(rgb24Data), 1, rgb24File);
    
    rgb24ToYuv444p(rgb24Data, yuv444pData, width, height);

    FILE *yuv444pFile = fopen("/Users/ff/Desktop/rainbow-rgb24-to-yuv444p.yuv", "wb");
    fwrite(yuv444pData, sizeof(yuv444pData), 1, yuv444pFile);
    
    fclose(rgb24File);
    fclose(yuv444pFile);
    return 0;
}
ffplay -f rawvideo -pix_fmt rgb24 -video_size 700x700 rainbow-rgb24.rgb
ffplay -f rawvideo -pix_fmt yuv444p -video_size 700x700 rainbow-rgb24-to-yuv444p.yuv

YUV -> RGB

Convert YUV444P format generated by FFmpeg to RGB24 format.
[rainbow-yuv444p.yuv] -> [rainbow-yuv444p-to-rgb24.rgb]

#include <stdio.h>
#include <math.h>


u_int8_t bound(u_int8_t start, int value, u_int8_t end) {
    if(value <= start) {
        return start;
    }
    if(value >= end) {
        return end;
    }
    return value;
}


void yuv444pToRGB(u_int8_t *yuv444pData,u_int8_t *rgb24Data, int width, int height) {
    u_int8_t *srcY = yuv444pData, *srcU = srcY + width * height, *srcV = srcU + width * height;

    for(int i = 0 ; i < height ; i ++) {
        for (int j = 0; j < width; j++) {
            int currentYUVIndex = i * height + j;
            u_int8_t Y = srcY[currentYUVIndex], U = srcU[currentYUVIndex], V = srcV[currentYUVIndex];

            int r_val = (int)round(1.164*(Y-16)+1.596*(V-128));
            int g_val = (int)round(1.164*(Y-16)-0.813*(V-128)-0.391*(U-128));
            int b_val = (int)round(1.164*(Y-16)+2.018*(U-128));

            int currentRGBIndex = 3*(i * width + j);
            rgb24Data[currentRGBIndex] = bound(0, r_val, 255);
            rgb24Data[currentRGBIndex+1] = bound(0, g_val, 255);
            rgb24Data[currentRGBIndex+2] = bound(0, b_val, 255);
        }
    }
}

int main() {
    int width = 700, height = 700;
    u_int8_t yuv444pData[width*height*3];
    u_int8_t rgb24Data[width*height*3];

    FILE *yuv444pFile = fopen("/Users/staff/Desktop/rainbow-yuv444p.yuv", "rb");
    fread(yuv444pData, sizeof(yuv444pData), 1, yuv444pFile);

     yuv444pToRGB(yuv444pData, rgb24Data, width, height);

    FILE *rgb24File = fopen("/Users/staff/Desktop/rainbow-yuv444p-to-rgb24.rgb", "wb");
    fwrite(rgb24Data, sizeof(rgb24Data), 1, rgb24File);

    fclose(yuv444pFile);
    fclose(rgb24File);
    return 0;
}
ffplay -f rawvideo -pix_fmt yuv444p -video_size 700x700 rainbow-yuv444p.yuv
ffplay -f rawvideo -pix_fmt rgb24 -video_size 700x700 rainbow-yuv444p-to-rgb24.rgb

Verify using colorful pictures

Prepare a Disney.png for your mobile phone

ffmpeg -i Disney.png -video_size 700x700 -pix_fmt yuv444p Disney-yuv444p.yuv
ffmpeg -i Disney.png -video_size 700x700 -pix_fmt rgb24 Disney-rgb24.rgb
ffplay -f rawvideo -pix_fmt yuv444p -video_size 700x700 Disney-yuv444p.yuv
ffplay -f rawvideo -pix_fmt rgb24 -video_size 700x700 Disney-rgb24.rgb

Using the above code to convert to Disney-rgb24-to-yuv444p.yuv Disney-yuv444p-to-rgb24.rgb

Congratulations!

Code:
08-rgb-to-yuv

Reference material:

Formula and C++ code for conversion between YUV format and RGB format

Color Conversion

videolan-YUV

Blog Directory - Technology - Video Processing

YUV format learning: YUV420P, YV12, NV12, NV21 formats converted to RGB24

Introduction of image RGB2YUV and YUV2RGB format conversion

Optimal algorithm for YUV to RGB

Formula and C++ code for conversion between YUV format and RGB format

YUV420 and YUV444 are interoperable, YUV420 and YUV444 are read and saved, YUV display and play functions

Differences between YCbCr and YUV

Wikipedia-YUV

Wikipedia-YCbCr

Wrong content?Contact author:

Posted by fizzystutter on Wed, 18 Sep 2019 19:32:12 -0700