• 音视频入门-09-RGB&YUV互转-使用开源库


    * 音视频入门文章目录 *

    介绍开源库

    使用第三方开源库来简化开发,屏蔽一些底层的复杂度,节省大量编写代码的时间。

    libyuv: Google 开源的实现各种 YUV 与 RGB 之间相互转换、旋转、缩放的库。

    yuv2rgb:C library for fast image conversion between yuv420p and rgb24.

    使用开源库

    libyuv

    FFmpeg 生成代码所需文件:

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

    YUV444P to RGB32

    将 FFmpeg 生成的 YUV444P 格式转换成 RGB32 格式。
    [rainbow-yuv444p.yuv] -> [rainbow-yuv444p-to-rgb32-libyuv.rgb]

    #include <stdio.h>
    #include "libyuv.h"
    
    void libyuv_I444_to_Rgb(char *srcFileName, char *dstFileName, int width, int height) {
        FILE *src_file = fopen(srcFileName, "rb");
        FILE *dst_file = fopen(dstFileName, "wb");
    
        int size_src = width * height * 3;
        int size_dest = width * height * 4;
        char *buffer_src = (char *)malloc(size_src);
        char *buffer_dest = (char *)malloc(size_dest);
    
        fread(buffer_src, 1, size_src, src_file);
        
        I444ToARGB(
            (const u_int8_t*)buffer_src, width,
            (const u_int8_t*)(buffer_src + width * height), width,
            (const u_int8_t*)(buffer_src + 2 * width * height), width,
            (u_int8_t*)buffer_dest, width * 4,
            width, height);
        
        fwrite(buffer_dest, 1, size_dest, dst_file);
    
        free(buffer_src);
        free(buffer_dest);
        fclose(dst_file);
        fclose(src_file);
    }
    
    int main() {
        int width = 700, height = 700;
        libyuv_I444_to_Rgb("/Users/staff/Desktop/rainbow-yuv444p.yuv", "/Users/staff/Desktop/rainbow-yuv444p-to-rgb32-libyuv.yuv", width, height);
        return 0;
    }
    

    FFplay 显示生成的 rainbow-yuv444p-to-rgb32-libyuv.rgb

    ffplay -f rawvideo -pixel_format rgb32 -video_size 700x700 rainbow-yuv444p-to-rgb32-libyuv.rgb
    

    yuv444p-to-rgb32-libyuv.jpg

    RGB24 to YUV420p

    将 FFmpeg 生成的 RGB24 格式转换成 YUV420p 格式。
    [rainbow-rgb24.rgb] -> [rainbow-rgb24-to-yuv420p-libyuv.yuv]

    #include <stdio.h>
    #include "libyuv.h"
    
    void libyuv_Rgb24_to_Yuv420p(char *rgbFileName, char *yuvFileName, int width, int height) {
        FILE *rgb_file = fopen(rgbFileName, "rb");
        FILE *yuv_file = fopen(yuvFileName, "wb");
    
        int size_rgb = width * height * 3;
        int size_yuv = width * height * 3 / 2;
        uint8_t *buffer_rgb = (uint8_t *)malloc(size_rgb);
        uint8_t *buffer_yuv = (uint8_t *)malloc(size_yuv);
    
        fread(buffer_rgb, 1, size_rgb, rgb_file);
    
        // RGB to BGR
    //    uint8_t temp;
    //    for(int i = 0; i < size_rgb; i+=3) {
    //        temp = buffer_rgb[i + 0];
    //        buffer_rgb[i + 0] = buffer_rgb[i + 2];
    //        buffer_rgb[i + 2] = temp;
    //    }
    
    //    RGB24ToI420(
        RAWToI420(
                buffer_rgb, width*3,
                buffer_yuv, width,
                buffer_yuv + width*height, (width+1)/2,
                buffer_yuv + width*height + ((width+1)/2)*((height+1)/2), (width+1)/2,
                width, height);
    
        fwrite(buffer_yuv, 1, size_yuv, yuv_file);
    
        free(buffer_rgb);
        free(buffer_yuv);
        fclose(yuv_file);
        fclose(rgb_file);
    }
    
    int main() {
        int width = 700, height = 700;
        libyuv_Rgb24_to_Yuv420p("/Users/staff/Desktop/rainbow-rgb24.rgb", "/Users/staff/Desktop/rainbow-rgb24-to-yuv420p-libyuv.yuv", width, height);
        return 0;
    }
    

    FFplay 显示生成的 rainbow-rgb24-to-yuv420p-libyuv.yuv

    ffplay -f rawvideo -pixel_format yuv420p -video_size 700x700 rainbow-rgb24-to-yuv420p-libyuv.yuv
    

    rgb24-to-yuv420p-libyuv.png

    descampsa/yuv2rgb

    YUV420p to RGB24

    将 FFmpeg 生成的 YUV420P 格式转换成 RGB24 格式。
    [rainbow-yuv420p.yuv] -> [rainbow-yuv420p-to-rgb24-descampsa.rgb]

    #include <stdio.h>
    #include "descampsa/yuv2rgb/yuv_rgb.h"
    
    void yuv420pToRgb24(uint8_t *YUV, uint8_t *RGB, uint32_t width, uint32_t height) {
        const YCbCrType yuv_format = YCBCR_601;
        // const YCbCrType yuv_format = YCBCR_709;
        // const YCbCrType yuv_format = YCBCR_JPEG;
    
        yuv420_rgb24_std(
            width,
            height,
            YUV,
            YUV+width*height,
            YUV+width*height+((width+1)/2)*((height+1)/2),
            width,
            (width+1)/2,
            RGB,
            width*3,
            yuv_format);
    
    }
    
    int main() {
        uint32_t width = 700, height = 700;
        uint8_t RGB[width*height*3];
        uint8_t YUV[width*height*3/2];
    
        FILE *yuv420pFile = fopen("/Users/staff/Desktop/rainbow-yuv420p.yuv", "rb");
        fread(YUV, sizeof(YUV), 1, yuv420pFile);
    
        yuv420pToRgb24(YUV, RGB, width, height);
    
        FILE *rgb24File = fopen("/Users/staff/Desktop/rainbow-yuv420p-to-rgb24-descampsa.rgb", "wb");
        fwrite(RGB, sizeof(RGB), 1, rgb24File);
    
        fclose(rgb24File);
        fclose(yuv420pFile);
        return 0;
    }
    

    FFplay 显示生成的 rainbow-yuv420p-to-rgb24-descampsa.rgb

    ffplay -f rawvideo -pixel_format rgb24 -video_size 700x700 rainbow-yuv420p-to-rgb24-descampsa.rgb
    

    yuv420p-to-rgb24-descampsa.jpg

    RGB24 to YUV420p

    将 FFmpeg 生成的 RGB24 格式转换成 YUV420p 格式。
    [rainbow-rgb24.rgb] -> [rainbow-rgb24-to-yuv420p-descampsa.yuv]

    #include <stdio.h>
    #include "descampsa/yuv2rgb/yuv_rgb.h"
    
    void rgb24ToYuv420p(uint8_t *RGB, uint8_t *YUV, uint32_t width, uint32_t height) {
        const YCbCrType yuv_format = YCBCR_601;
    //    const YCbCrType yuv_format = YCBCR_709;
        //const YCbCrType yuv_format = YCBCR_JPEG;
    
        rgb24_yuv420_std(
            width,
            height,
            RGB,
            width*3,
            YUV,
            YUV+width*height,
            YUV+width*height+((width+1)/2)*((height+1)/2),
            width,
            width/2,
            yuv_format);
    }
    
    int main() {
        uint32_t width = 700, height = 700;
        uint8_t RGB[width*height*3];
        uint8_t YUV[width*height*3/2];
    
        FILE *rgb24File = fopen("/Users/staff/Desktop/rainbow-rgb24.rgb", "rb");
        fread(RGB, sizeof(RGB), 1, rgb24File);
    
        rgb24ToYuv420p(RGB, YUV, width, height);
    
        FILE *yuvFile = fopen("/Users/staff/Desktop/rainbow-rgb24-to-yuv420p-descampsa.yuv", "wb");
        fwrite(YUV, sizeof(YUV), 1, yuvFile);
    
        fclose(rgb24File);
        fclose(yuvFile);
        return 0;
    }
    

    FFplay 显示生成的 rainbow-rgb24-to-yuv420p-descampsa.yuv

    ffplay -f rawvideo -pixel_format yuv420p -video_size 700x700 rainbow-rgb24-to-yuv420p-descampsa.yuv
    

    rgb24-to-yuv420p-descampsa.jpg


    代码:
    09-rgb-to-yuv-library

    参考资料:

    libyuv/libyuv

    descampsa/yuv2rgb

    latelee/yuv2rgb

    dmilos/color

    ibireme/yy_color_convertor

    andrechen/yuv2rgb

    内容有误?联系作者:

    联系作者


  • 相关阅读:
    第 01 组 Alpha 事后诸葛亮
    第 01 组 Alpha 冲刺(4/4)
    第 01 组 Alpha 冲刺(3/4)
    第 01 组 Alpha 冲刺(2/4)
    第 01 组 Alpha 冲刺(1/4)
    学习日志-2021.11.08
    论文阅读-2021.11.06
    学习日志-2021.10.25
    学习日志-2021.10.24
    学习日志-2021.10.18
  • 原文地址:https://www.cnblogs.com/binglingziyu/p/audio-video-basic-09-rgb-and-yuv-library.html
Copyright © 2020-2023  润新知