YUV<->RGB互转程序以及octave验证

本文详细介绍了如何使用C语言编写程序,通过CCIR601和ISBN1-878707-09-4标准,实现RGB(红绿蓝)到YUV(亮度、色度)的转换,并通过实例验证了转换的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转换数学公式

转换公式如下:

\boldsymbol{\begin{bmatrix} Y\\ U\\ V \end{bmatrix}=\begin{bmatrix} 0.299000 &0.587000 & 0.114000 \\ -0.169000 & -0.331000 & 0.500000 \\ 0.500000 &-0.419000 & -0.081000 \end{bmatrix}\cdot \begin{bmatrix} R\\ G\\ B \end{bmatrix} + \begin{bmatrix} 0\\ 128\\ 128 \end{bmatrix}}

C实现

YUV和RGB互转C程序如下:

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

#define DEBUG

#if defined(DEBUG)
#define debug printf
#else
#define debug
#endif

int main(int argc, char* argv[])
{
    unsigned int input_rgb;
    unsigned char input_r, input_g, input_b;
    unsigned char output_y, output_u, output_v;
    float r, g, b;
    float y, u, v;

    /* 打印函数使用方法 */
    if(argc !=  2)
    {
        printf("usage: ./app <RGB888 color>\n");
        printf("eg   : ./app 0xFF0000\n");
        printf("\n");
        return -1;
    }

    if(strlen(argv[1]) != 8)
    {
        printf("please enter Full color value\n");
        printf("  eg1: 0xFFFFFF\n");
        printf("  eg2: 0xFF0000\n");
        printf("  eg3: 0x123456\n\n");
        printf("The following format is incorrect\n");
        printf("  err fmt1: 0xFF00\n");
        printf("  err fmt2: FF0000\n");
        printf("  err fmt2: 0xxFFFFF\n\n");
        printf("\n");
        return -1;
    }

    input_rgb = (unsigned int)strtol(argv[1], NULL, 0);
    debug("input_rgb = 0x%x\n", input_rgb);

    input_r = input_rgb >> 16;
    input_g = input_rgb >> 8;
    input_b = input_rgb;
    debug("input_r   = 0x%2x(h), %3d(d)\n", input_r, input_r);
    debug("input_g   = 0x%2x(h), %3d(d)\n", input_g, input_g);
    debug("input_b   = 0x%2x(h), %3d(d)\n", input_b, input_b);

    r = (float)input_r;
    g = (float)input_g;
    b = (float)input_b;
    debug("r         = %f\n", r);
    debug("g         = %f\n", g);
    debug("b         = %f\n", b);

#if 1
    /* CCIR 601 */
    /* RGB和YUV的范围都是[0,255] */
    y =  0.299 * r + 0.587 * g + 0.114 * b;
    v =  0.500 * r - 0.419 * g - 0.081 * b + 128;
    u = -0.169 * r - 0.331 * g + 0.500 * b + 128;
#else
    /* ISBN 1-878707-09-4 */
    /* RGB的范围是[0,255], Y的范围是[16,235], UV的范围是[16,239] */
    y =  0.257 * r + 0.504 * g + 0.098 * b + 16;
    v =  0.439 * r - 0.368 * g - 0.071 * b + 128;
    u = -0.148 * r - 0.291 * g + 0.439 * b + 128;
#endif

    debug("y = %f\n", y);
    debug("u = %f\n", u);
    debug("v = %f\n", v);

    /* float 类型强转为整形,做四舍五入转化的话,原本是要加 0.5 的 */
    /* 但是由于 FF 的颜色值,计算到的 YUV 分量的值为 255.5, 再加 0.5 后数据会溢出 */
    /* 因此这里迫不得已加 0.4999 将就一下 */
    output_y = (unsigned char)(y + 0.4999);
    output_u = (unsigned char)(u + 0.4999);
    output_v = (unsigned char)(v + 0.4999);
    printf("y = 0x%2x(hex), %3d(dec), %f(f)\n", output_y, output_y, y);
    printf("u = 0x%2x(hex), %3d(dec), %f(f)\n", output_u, output_u, u);
    printf("v = 0x%2x(hex), %3d(dec), %f(f)\n", output_v, output_v, v);

    printf("\n");
    return 0;
}

分别用RGB的红,绿,蓝以及黑色和白色来验证:

caozilong@AwExdroid65:~/WorkSpace/yuvrgb$ ./a.out 0xff0000
input_rgb = 0xff0000
input_r   = 0xff(h), 255(d)
input_g   = 0x 0(h),   0(d)
input_b   = 0x 0(h),   0(d)
r         = 255.000000
g         = 0.000000
b         = 0.000000
y = 76.245003
u = 84.904999
v = 255.500000
y = 0x4c(hex),  76(dec), 76.245003(f)
u = 0x55(hex),  85(dec), 84.904999(f)
v = 0xff(hex), 255(dec), 255.500000(f)

caozilong@AwExdroid65:~/WorkSpace/yuvrgb$
caozilong@AwExdroid65:~/WorkSpace/yuvrgb$ ls
a.out  main.c
caozilong@AwExdroid65:~/WorkSpace/yuvrgb$ ./a.out 0xff0000
input_rgb = 0xff0000
input_r   = 0xff(h), 255(d)
input_g   = 0x 0(h),   0(d)
input_b   = 0x 0(h),   0(d)
r         = 255.000000
g         = 0.000000
b         = 0.000000
y = 76.245003
u = 84.904999
v = 255.500000
y = 0x4c(hex),  76(dec), 76.245003(f)
u = 0x55(hex),  85(dec), 84.904999(f)
v = 0xff(hex), 255(dec), 255.500000(f)

caozilong@AwExdroid65:~/WorkSpace/yuvrgb$
caozilong@AwExdroid65:~/WorkSpace/yuvrgb$ ls
a.out  main.c
caozilong@AwExdroid65:~/WorkSpace/yuvrgb$ gcc main.c
caozilong@AwExdroid65:~/WorkSpace/yuvrgb$ ./a.out 0xff0000
input_rgb = 0xff0000
input_r   = 0xff(h), 255(d)
input_g   = 0x 0(h),   0(d)
input_b   = 0x 0(h),   0(d)
r         = 255.000000
g         = 0.000000
b         = 0.000000
y = 76.245003
u = 84.904999
v = 255.500000
y = 0x4c(hex),  76(dec), 76.245003(f)
u = 0x55(hex),  85(dec), 84.904999(f)
v = 0xff(hex), 255(dec), 255.500000(f)

caozilong@AwExdroid65:~/WorkSpace/yuvrgb$ ./a.out 0x00ff00
input_rgb = 0xff00
input_r   = 0x 0(h),   0(d)
input_g   = 0xff(h), 255(d)
input_b   = 0x 0(h),   0(d)
r         = 0.000000
g         = 255.000000
b         = 0.000000
y = 149.684998
u = 43.595001
v = 21.155001
y = 0x96(hex), 150(dec), 149.684998(f)
u = 0x2c(hex),  44(dec), 43.595001(f)
v = 0x15(hex),  21(dec), 21.155001(f)

caozilong@AwExdroid65:~/WorkSpace/yuvrgb$ ./a.out 0x0000ff
input_rgb = 0xff
input_r   = 0x 0(h),   0(d)
input_g   = 0x 0(h),   0(d)
input_b   = 0xff(h), 255(d)
r         = 0.000000
g         = 0.000000
b         = 255.000000
y = 29.070000
u = 255.500000
v = 107.345001
y = 0x1d(hex),  29(dec), 29.070000(f)
u = 0xff(hex), 255(dec), 255.500000(f)
v = 0x6b(hex), 107(dec), 107.345001(f)

caozilong@AwExdroid65:~/WorkSpace/yuvrgb$ ./a.out 0xffffff
input_rgb = 0xffffff
input_r   = 0xff(h), 255(d)
input_g   = 0xff(h), 255(d)
input_b   = 0xff(h), 255(d)
r         = 255.000000
g         = 255.000000
b         = 255.000000
y = 255.000000
u = 128.000000
v = 128.000000
y = 0xff(hex), 255(dec), 255.000000(f)
u = 0x80(hex), 128(dec), 128.000000(f)
v = 0x80(hex), 128(dec), 128.000000(f)

caozilong@AwExdroid65:~/WorkSpace/yuvrgb$ ./a.out 0x000000
input_rgb = 0x0
input_r   = 0x 0(h),   0(d)
input_g   = 0x 0(h),   0(d)
input_b   = 0x 0(h),   0(d)
r         = 0.000000
g         = 0.000000
b         = 0.000000
y = 0.000000
u = 128.000000
v = 128.000000
y = 0x 0(hex),   0(dec), 0.000000(f)
u = 0x80(hex), 128(dec), 128.000000(f)
v = 0x80(hex), 128(dec), 128.000000(f)

caozilong@AwExdroid65:~/WorkSpace/yuvrgb$

octave验证:


参考资料:

https://zh.wikipedia.org/wiki/%E5%B8%83%E9%9B%B7%E6%A3%AE%E6%BC%A2%E5%A7%86%E7%9B%B4%E7%B7%9A%E6%BC%94%E7%AE%97%E6%B3%95

Bresenham

结束!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

papaofdoudou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值