实现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,因此需要做一个电平的补偿,最终得到的公式为:
同理,运用上面公式将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输出文件如下:
上一篇: Hive数据压缩和存储格式
下一篇: RGB与YUV文件的互转