stb (c++) yuv转rgb

目录

BT601协议

BT709协议

BT2020协议

图片效果对比


在上一节stb (c++) uv(nv12)恢复

我们得到了

full_U[w*h], full_V[w*h]

再加上

Y

协议

  • https://blog.csdn.net/m18612362926/article/details/127667954

  • https://blog.csdn.net/u010186001/article/details/52800250

在之前内容里,Y范围: [16,235]

BT601协议

信号类型:数字 TV range

#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb/stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb/stb_image_write.h"
#include <fstream>

using namespace std;

int main()
{
    char c;
    unsigned char uchar;

    int w=400,h=328;
    int Y_max = w*h;
    int Y_index = 0;
    int UV_mark = 0, U_index=0, V_index=0;
    float Y[w*h],U[w*h/4],V[w*h/4];

    ifstream read;
    read.open("s_l-nv12.yuv");
    
    while (read.get(c))
    {
        uchar = c;
        if (Y_index<Y_max)
        {
            Y[Y_index] = uchar; 
            Y_index += 1;
        }
        else{
            if(UV_mark % 2 == 0) { U[U_index]=uchar; U_index +=1; }
            else{ V[V_index]=uchar; V_index +=1; }
            UV_mark += 1;
        }
    }
    cout << "Y范围: [" << *min_element(Y,Y+w*h) << "," << *max_element(Y,Y+w*h) << "]" << endl;
    cout << "U范围: [" << *min_element(U,U+w*h/4) << "," << *max_element(U,U+w*h/4) << "]" << endl;
    cout << "V范围: [" << *min_element(V,V+w*h/4) << "," << *max_element(V,V+w*h/4) << "]" << endl;

    float full_U[w*h], full_V[w*h];
    U_index=0; V_index=0;
    for (int i=0; i<h; i++)
    {
        if ((i+1)%2==0)
        {
            for (int j=0; j<w; j++)
            {
                if (j%2==0)
                {
                    full_U[i*w+j] = U[U_index];
                    full_U[i*w+j+1] = U[U_index];
                    full_U[(i-1)*w+j] = U[U_index];
                    full_U[(i-1)*w+j+1] = U[U_index];
                    U_index += 1;

                    full_V[i*w+j] = V[V_index];
                    full_V[i*w+j+1] = V[V_index];
                    full_V[(i-1)*w+j] = V[V_index];
                    full_V[(i-1)*w+j+1] = V[V_index];
                    V_index += 1;
                }
            }
        }
    }

    float temp_fR,temp_fG,temp_fB;
    int temp_iR,temp_iG,temp_iB;
    unsigned char temp_ucR,temp_ucG,temp_ucB;
    
    cout << "-----------\n";
    auto *rgb_data = (unsigned char *) malloc(w*h*3);
    for(int i=0;i<h;i++)
    {
        for(int j=0;j<w;j++)
        {
            temp_fR = 1.164*(Y[i*w+j]-16)+1.596*(full_V[i*w+j]-128);
            temp_iR = temp_fR;
            if(temp_iR>255){temp_iR=255;}
            if(temp_iR<0){temp_iR=0;}
            temp_ucR = temp_iR;
            rgb_data[i*w*3+j*3+0] = temp_ucR;

            temp_fG = 1.164*(Y[i*w+j]-16)-0.392*(full_U[i*w+j]-128)-0.812*(full_V[i*w+j]-128);
            temp_iG = temp_fG;
            if(temp_iG>255){temp_iG=255;}
            if(temp_iG<0){temp_iG=0;}
            temp_ucG = temp_iG;
            rgb_data[i*w*3+j*3+1] = temp_ucG;

            temp_fB = 1.164*(Y[i*w+j]-16)+2.016*(full_U[i*w+j]-128);
            temp_iB = temp_fB;
            if(temp_iB>255){temp_iB=255;}
            if(temp_iB<0){temp_iB=0;}
            temp_ucB = temp_iB;
            rgb_data[i*w*3+j*3+2] = temp_ucB;
        }
        
    }
    string name = "s_l-nv12-BT601-TV_range.jpg";
    stbi_write_jpg(name.c_str(), w, h, 3, rgb_data, 95);
    stbi_image_free(rgb_data);
}

BT709协议

信号类型:数字 TV range

#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb/stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb/stb_image_write.h"
#include <fstream>

using namespace std;

int main()
{
    char c;
    unsigned char uchar;

    int w=400,h=328;
    int Y_max = w*h;
    int Y_index = 0;
    int UV_mark = 0, U_index=0, V_index=0;
    float Y[w*h],U[w*h/4],V[w*h/4];

    ifstream read;
    read.open("s_l-nv12.yuv");
    
    while (read.get(c))
    {
        uchar = c;
        if (Y_index<Y_max)
        {
            Y[Y_index] = uchar; 
            Y_index += 1;
        }
        else{
            if(UV_mark % 2 == 0) { U[U_index]=uchar; U_index +=1; }
            else{ V[V_index]=uchar; V_index +=1; }
            UV_mark += 1;
        }
    }
    cout << "Y范围: [" << *min_element(Y,Y+w*h) << "," << *max_element(Y,Y+w*h) << "]" << endl;
    cout << "U范围: [" << *min_element(U,U+w*h/4) << "," << *max_element(U,U+w*h/4) << "]" << endl;
    cout << "V范围: [" << *min_element(V,V+w*h/4) << "," << *max_element(V,V+w*h/4) << "]" << endl;

    float full_U[w*h], full_V[w*h];
    U_index=0; V_index=0;
    for (int i=0; i<h; i++)
    {
        if ((i+1)%2==0)
        {
            for (int j=0; j<w; j++)
            {
                if (j%2==0)
                {
                    full_U[i*w+j] = U[U_index];
                    full_U[i*w+j+1] = U[U_index];
                    full_U[(i-1)*w+j] = U[U_index];
                    full_U[(i-1)*w+j+1] = U[U_index];
                    U_index += 1;

                    full_V[i*w+j] = V[V_index];
                    full_V[i*w+j+1] = V[V_index];
                    full_V[(i-1)*w+j] = V[V_index];
                    full_V[(i-1)*w+j+1] = V[V_index];
                    V_index += 1;
                }
            }
        }
    }

    float temp_fR,temp_fG,temp_fB;
    int temp_iR,temp_iG,temp_iB;
    unsigned char temp_ucR,temp_ucG,temp_ucB;
    
    cout << "-----------\n";
    auto *rgb_data = (unsigned char *) malloc(w*h*3);
    for(int i=0;i<h;i++)
    {
        for(int j=0;j<w;j++)
        {
            temp_fR = 1.164*(Y[i*w+j]-16)+1.792*(full_V[i*w+j]-128);
            temp_iR = temp_fR;
            if(temp_iR>255){temp_iR=255;}
            if(temp_iR<0){temp_iR=0;}
            temp_ucR = temp_iR;
            rgb_data[i*w*3+j*3+0] = temp_ucR;

            temp_fG = 1.164*(Y[i*w+j]-16)-0.213*(full_U[i*w+j]-128)-0.534*(full_V[i*w+j]-128);
            temp_iG = temp_fG;
            if(temp_iG>255){temp_iG=255;}
            if(temp_iG<0){temp_iG=0;}
            temp_ucG = temp_iG;
            rgb_data[i*w*3+j*3+1] = temp_ucG;

            temp_fB = 1.164*(Y[i*w+j]-16)+2.114*(full_U[i*w+j]-128);
            temp_iB = temp_fB;
            if(temp_iB>255){temp_iB=255;}
            if(temp_iB<0){temp_iB=0;}
            temp_ucB = temp_iB;
            rgb_data[i*w*3+j*3+2] = temp_ucB;
        }  
    }
    string name = "s_l-nv12-BT709-TV_range.jpg";
    stbi_write_jpg(name.c_str(), w, h, 3, rgb_data, 95);
    stbi_image_free(rgb_data);
}

BT2020协议

信号类型:数字 TV range

#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb/stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb/stb_image_write.h"
#include <fstream>

using namespace std;

int main()
{
    char c;
    unsigned char uchar;

    int w=400,h=328;
    int Y_max = w*h;
    int Y_index = 0;
    int UV_mark = 0, U_index=0, V_index=0;
    float Y[w*h],U[w*h/4],V[w*h/4];

    ifstream read;
    read.open("s_l-nv12.yuv");
    
    while (read.get(c))
    {
        uchar = c;
        if (Y_index<Y_max)
        {
            Y[Y_index] = uchar; 
            Y_index += 1;
        }
        else{
            if(UV_mark % 2 == 0) { U[U_index]=uchar; U_index +=1; }
            else{ V[V_index]=uchar; V_index +=1; }
            UV_mark += 1;
        }
    }
    cout << "Y范围: [" << *min_element(Y,Y+w*h) << "," << *max_element(Y,Y+w*h) << "]" << endl;
    cout << "U范围: [" << *min_element(U,U+w*h/4) << "," << *max_element(U,U+w*h/4) << "]" << endl;
    cout << "V范围: [" << *min_element(V,V+w*h/4) << "," << *max_element(V,V+w*h/4) << "]" << endl;

    float full_U[w*h], full_V[w*h];
    U_index=0; V_index=0;
    for (int i=0; i<h; i++)
    {
        if ((i+1)%2==0)
        {
            for (int j=0; j<w; j++)
            {
                if (j%2==0)
                {
                    full_U[i*w+j] = U[U_index];
                    full_U[i*w+j+1] = U[U_index];
                    full_U[(i-1)*w+j] = U[U_index];
                    full_U[(i-1)*w+j+1] = U[U_index];
                    U_index += 1;

                    full_V[i*w+j] = V[V_index];
                    full_V[i*w+j+1] = V[V_index];
                    full_V[(i-1)*w+j] = V[V_index];
                    full_V[(i-1)*w+j+1] = V[V_index];
                    V_index += 1;
                }
            }
        }
    }

    float temp_fR,temp_fG,temp_fB;
    int temp_iR,temp_iG,temp_iB;
    unsigned char temp_ucR,temp_ucG,temp_ucB;
    
    cout << "-----------\n";
    auto *rgb_data = (unsigned char *) malloc(w*h*3);
    for(int i=0;i<h;i++)
    {
        for(int j=0;j<w;j++)
        {
            temp_fR = 1.164*(Y[i*w+j]-16)+1.6853*(full_V[i*w+j]-128);
            temp_iR = temp_fR;
            if(temp_iR>255){temp_iR=255;}
            if(temp_iR<0){temp_iR=0;}
            temp_ucR = temp_iR;
            rgb_data[i*w*3+j*3+0] = temp_ucR;

            temp_fG = 1.164*(Y[i*w+j]-16)-0.1881*(full_U[i*w+j]-128)-0.6529*(full_V[i*w+j]-128);
            temp_iG = temp_fG;
            if(temp_iG>255){temp_iG=255;}
            if(temp_iG<0){temp_iG=0;}
            temp_ucG = temp_iG;
            rgb_data[i*w*3+j*3+1] = temp_ucG;

            temp_fB = 1.164*(Y[i*w+j]-16)+2.1501*(full_U[i*w+j]-128);
            temp_iB = temp_fB;
            if(temp_iB>255){temp_iB=255;}
            if(temp_iB<0){temp_iB=0;}
            temp_ucB = temp_iB;
            rgb_data[i*w*3+j*3+2] = temp_ucB;
        }  
    }
    string name = "s_l-nv12-BT2020-TV_range.jpg";
    stbi_write_jpg(name.c_str(), w, h, 3, rgb_data, 95);
    stbi_image_free(rgb_data);
}

图片效果对比

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值