欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

实现RGB文件与YUV文件相互转化

程序员文章站 2022-07-14 22:06:29
...

将RGB文件转为YUV文件,我们需要将图像的RGB三个分量转化为YUV分量,由公式可知:
Y = 0.299R + 0.587G + 0.114B
U = 0.564
(B - Y)
V = 0.713*(R - Y)
而对于上述公式,我们需要进行8bit量化,同时,对于U、V信号,我们要将范围控制在16—240之间
对于Y信号,则要将范围控制在16—235之间,同时又因为计算所得的Y信号下限为16,U、V下限为-128,因此需要做一个电平的补偿,最终得到的公式为:
实现RGB文件与YUV文件相互转化
同理,运用上面公式将YUV文件转回RGB文件公式为:
实现RGB文件与YUV文件相互转化
在本次实验中我尝试了用命令行参数传递读取文件的地址信息,在Code::Block中设置如下:

project>>set programs arguments
实现RGB文件与YUV文件相互转化
这样就将输入图片地址和输出图像地址以及长宽信息传递进函数了。
main函数如下:

#include"iostream"
#include"math.h"
#include"stdio.h"
#include"malloc.h"
#include"rgb2yuv.h"
#include"yuv2rgb.h"
using namespace std;
int main(int argc, char* argv[]){
    char* imgaddr = argv[1];
    char* yuvaddr = argv[2];
    int W = atoi(argv[3]);
    int H = atoi(argv[4]);
    int imgsize = W*H*3;
    unsigned char* imgbuffer = new unsigned char[imgsize];
    unsigned char* Rbuffer = new unsigned char[imgsize/3];
    unsigned char* Gbuffer = new unsigned char[imgsize/3];
    unsigned char* Bbuffer = new unsigned char[imgsize/3];
    
    FILE* imgopen = fopen(imgaddr,"rb");
    if(imgopen == NULL){
        cout<<"打开rgb文件失败"<<endl;
    }
    FILE* yuvsave = fopen(yuvaddr,"w");
    if(yuvsave == NULL){
        cout<<"创建yuv空白文件失败"<<endl;
    }
    
    transf(Rbuffer, Gbuffer, Bbuffer, imgbuffer, imgopen, yuvsave, W, H);
    
    char* recoimgaddr = argv[5];
    FILE* saverec = fopen(recoimgaddr,"w");
    FILE* openyuv = fopen(yuvaddr,"rb");
    if(saverec == NULL){
        cout<<"创建恢复文件失败"<<endl;
    }
    int yuvFileSize;
    FILE* checkyuv = fopen(yuvaddr,"rb");
    fseek(checkyuv, 0L, SEEK_END);
    yuvFileSize = ftell(checkyuv);
    rewind(checkyuv);
    cout << "The yuv space is " << yuvFileSize << " Bytes = " << yuvFileSize / 1024 << " kB." << endl;
    unsigned char* ybuffer = new unsigned char[W*H];
    unsigned char* ubuffer = new unsigned char[W*H/4];
    unsigned char* vbuffer = new unsigned char[W*H/4];
    unsigned char* rgbbuffer = new unsigned char[3*W*H];
    fread(ybuffer, sizeof(unsigned char), W*H, openyuv);
    fread(ubuffer, sizeof(unsigned char), W*H/4, openyuv);
    fread(vbuffer, sizeof(unsigned char), W*H/4, openyuv);
    
    recov(openyuv, saverec, ybuffer, ubuffer, vbuffer, rgbbuffer, W, H);
     cout<<"all accomplished"<<endl;

rgb2yuv.h如下:

#ifndef RGB2YUV_H_INCLUDED
#define RGB2YUV_H_INCLUDED
#include"iostream"
#include"math.h"
#include"stdio.h"
#include"malloc.h"
using namespace std;
void transf(unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* rgb, FILE* open, FILE* out, int W, int H){
    unsigned char* ybuffer = new unsigned char[W*H];
    unsigned char* ubuffer = new unsigned char[W*H/4];
    unsigned char* vbuffer = new unsigned char[W*H/4];
    int i;
    int j;
    int coun=0;
    fread(rgb, sizeof(unsigned char), W*H*3, open);
    for(i = 0; i < W*H; i++){
        b[i] = rgb[3*i];
        g[i] = rgb[3*i+1];
        r[i] = rgb[3*i+2];
    }
    for(i = 0; i < H; i++){
        for(j = 0; j < W; j++){
            ybuffer[i*W+j] = ((66*r[i*W+j] + 129*g[i*W+j] + 25*b[i*W+j]) >> 8) + 16;
            if(!(i%2)&&!(j%2)){
                ubuffer[coun] = ((-38*r[coun] - 74*g[coun] + 112*b[coun]) >> 8) + 128;
                vbuffer[coun] = ((112*r[coun] - 94*g[coun] - 18*b[coun]) >> 8) + 128;
                coun++;
            }
        }
    }
   //for(i = 0; i < H; i++){
   //     for(j = 0; j < W; j++){
   //         ybuffer[i*W+j] = ((66 * r[i*W+j] + 129 * g[i*W+j] + 25 * b[i*W+j]) >> 8) + 16;
   //         ubuffer[i*W+j] = ((-38 * r[i*W+j] - 74 * g[i*W+j] + 112 * b[i*W+j]) >> 8) + 128;
   //         vbuffer[i*W+j] = ((112 * r[i*W+j] - 94 * g[i*W+j] - 18 * b[i*W+j]) >> 8) + 128;
   //     }
   // }
    fwrite(ybuffer, sizeof(unsigned char), W*H, out);
 fwrite(ubuffer, sizeof(unsigned char), W*H/4, out);
 fwrite(vbuffer, sizeof(unsigned char), W*H/4, out);
 cout<<"yuv file settled down"<<endl;
 delete ybuffer;
 delete ubuffer;
 delete vbuffer;
}
#endif // RGB2YUV_H_INCLUDED

yuv2rgb.h如下:

#ifndef YUV2RGB_H_INCLUDED
#define YUV2RGB_H_INCLUDED
#include"iostream"
#include"math.h"
#include"stdio.h"
#include"malloc.h"
using namespace std;
void recov(FILE* open, FILE* out, unsigned char* ybuffer, unsigned char* u42buffer, unsigned char* v42buffer, unsigned char* rgbbuffer, int W, int H){
    unsigned char* rbuffer = new unsigned char[W*H];
    unsigned char* gbuffer = new unsigned char[W*H];
    unsigned char* bbuffer = new unsigned char[W*H];
    unsigned char* ubuffer = new unsigned char[W*H];
    unsigned char* vbuffer = new unsigned char[W*H];
    int i;
    int m = 0;
    int n = 0;
    for(i = 0; i < W*H/4; i++){
        if(m >= W){
            m = 0;
            n += 2;
        }
        ubuffer[m+n*W] = u42buffer[i];
        ubuffer[m+1+n*W] = u42buffer[i];
        ubuffer[m+(n+1)*W] = u42buffer[i];
        ubuffer[m+1+(n+1)*W] = u42buffer[i];
        vbuffer[m+n*W] = v42buffer[i];
        vbuffer[m+1+n*W] = v42buffer[i];
        vbuffer[m+(n+1)*W] = v42buffer[i];
        vbuffer[m+1+(n+1)*W] = v42buffer[i];
        m += 2;
    }
    for(i = 0; i < W*H; i++){
        rbuffer[i] = (298*ybuffer[i] + 411*vbuffer[i] - 57344) >> 8;
        if(rbuffer[i] < 0){rbuffer[i] = 0;}
        if(rbuffer[i] > 255){rbuffer[i] = 255;}
        gbuffer[i] = (298*ybuffer[i] - 101*ubuffer[i] -211*vbuffer[i] + 34739) >> 8;
        if(gbuffer[i] < 0){gbuffer[i] = 0;}
        if(gbuffer[i] > 255){gbuffer[i] = 255;}
        bbuffer[i] = (298*ybuffer[i] + 519*ubuffer[i] - 71117) >> 8;
        if(bbuffer[i] < 0){bbuffer[i] = 0;}
        if(bbuffer[i] > 255){bbuffer[i] = 255;}
        rgbbuffer[3*i] = bbuffer[i];
        rgbbuffer[3*i+1] = gbuffer[i];
        rgbbuffer[3*i+2] = rbuffer[i];
    }
     fwrite(rgbbuffer, sizeof(unsigned char), 3*W*H, out);
 cout<<"rgb recovered from yuv"<<endl;
}
#endif // YUV2RGB_H_INCLUDED

输入图像如下:
实现RGB文件与YUV文件相互转化
YUV文件输出如下 :
实现RGB文件与YUV文件相互转化
RGB输出文件如下:

实现RGB文件与YUV文件相互转化