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

将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,因此需要做一个电平的补偿,最终得到的公式为:
这里因为传化为了420的YUV文件,因此UV分量需要求余进行选择
同理,运用上面公式将YUV文件转回RGB文件公式为:
同理,由420格式的YUV转化回RGB文件因为缺少数据,在这一步操作前需要进行数据的补齐
在本次实验中我尝试了用命令行参数传递读取文件的地址信息,在Code::Block中设置如下:

project>>set programs arguments
在这里插入图片描述
这样就将输入图片地址和输出图像地址以及长宽信息传递进函数了。
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

输入图像如下:
因读取软件原因,输出为反着的图
YUV文件输出如下 :
在这里插入图片描述
RGB输出文件如下:

因读取软件原因输出的是反着的图

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值