rgb2yuv
实验思路:
main函数关键代码:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "rgb2yuv.h"
#define u_int8_t unsigned __int8
#define u_int unsigned __int32
#define u_int32_t unsigned __int32
#define FALSE false
#define TRUE true
int main(int argc, char** argv)
{
u_int frameWidth = 352; /width/
u_int frameHeight = 240; /height/
bool flip = TRUE; /flip/
unsigned int i;
char* rgbFileName = NULL;
char* yuvFileName = NULL;
FILE* rgbFile = NULL;
FILE* yuvFile = NULL;
u_int8_t* rgbBuf = NULL;
u_int8_t* yBuf = NULL;
u_int8_t* uBuf = NULL;
u_int8_t* vBuf = NULL;
u_int32_t videoFramesWritten = 0;
rgbFileName = argv[1];
yuvFileName = argv[2];
frameWidth = atoi(argv[3]);
frameHeight = atoi(argv[4]);
rgbFile = fopen(rgbFileName, "rb");
if (rgbFile == NULL)
{
printf("cannot find rgb file\n");
exit(1);
}
else
{
printf("The input rgb file is %s\n", rgbFileName);
}
yuvFile = fopen(yuvFileName, "wb");
if (yuvFile == NULL)
{
printf("cannot find yuv file\n");
exit(1);
}
else
{
printf("The output yuv file is %s\n", yuvFileName);
}
rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3);
yBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
uBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);
vBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);
if (rgbBuf == NULL || yBuf == NULL || uBuf == NULL || vBuf == NULL)
{
printf("no enought memory\n");
exit(1);
}
while (fread(rgbBuf, 1, frameWidth * frameHeight * 3, rgbFile))
{
if(RGB2YUV(frameWidth, frameHeight, rgbBuf, yBuf, uBuf, vBuf, flip))
{
printf("error");
return 0;
}
for (i = 0; i < frameWidth*frameHeight; i++)
{
if (yBuf[i] < 16) yBuf[i] = 16;
if (yBuf[i] > 235) yBuf[i] = 235;
}
for (i = 0; i < frameWidth*frameHeight/4; i++)
{
if (uBuf[i] < 16) uBuf[i] = 16;
if (uBuf[i] > 240) uBuf[i] = 240;
if (vBuf[i] < 16) vBuf[i] = 16;
if (vBuf[i] > 240) vBuf[i] = 240;
}
fwrite(yBuf, 1, frameWidth * frameHeight, yuvFile);
fwrite(uBuf, 1, (frameWidth * frameHeight) / 4, yuvFile);
fwrite(vBuf, 1, (frameWidth * frameHeight) / 4, yuvFile);
printf("\r...%d", ++videoFramesWritten);
}
printf("\n%u %ux%u video frames written\n",
videoFramesWritten, frameWidth, frameHeight);
/* cleanup */
fclose(rgbFile);
fclose(yuvFile);
return(0);
YUV2RGB实验思路:
本次实验为YUV格式与RGB格式的转换,这里的YUV其实是指数字高清的YCbCr。
根据亮度和色差计算公式,可以得到:
Y=0.299R+0.587G+0.114B
Cr=R-Y=0.701R-0.587G-0.114B
Cb=B-Y=-0.299R-0.587G+0.886B
使色差信号的动态范围控制在-0.5~+0.5之间,要对色差信号进行归一化处理,得到UV的计算公式:
U=-0.1684R-0.3316G+0.5B
V=0.5R-0.4187G-0.0813B
由上式得到的UV范围在-128~+127之间,为避免负数,将其数值各扩大128达到非负。
-
YUV在存储时,为了防止信号变得造成过载,在对分量信号进行8比特均匀量化时,各自预留分量所限制的保护带,防止数值超越动态范围。
-
得到YUV转换RUV的公式:
B=Y+1.779U
G=Y-0.3455U-0.7169V
R=Y+1.4075V
注意:这里在计算RBG时应先将UV的值减128。
这里YUV采用的是4:2:0格式,即色度信号是亮度信号取样频率的四分之一。
主函数思路:
-
读取YUV文件,新建导出的RGB文件及空间
-
RGB文件是按照BGRBGRBGR……的顺序存储一帧的,所以RGB设定一个3倍像素数的数组,而YUV文件是YYYY……U……V……存储文件的,可以开辟一个像素数大小的数组存放Y分量和两个四分之一像素数大小的数组存放U和V分量。
-
读取图像YUV值存储于YUV三个缓存数组中
-
因为YUV有动态范围,需要判断Y和UV是否逾出
-
对YUV进行上采样,恢复出444格式的YUV。
-
按照转换公式,将每一个像素分别转换为RGB格式存在RGB缓存数组中。
#include <iostream>
#include"yuv2rgb. h"
#include" stdlib. h"
#include <malloc.h>
static float YUVRGB14075 [256] ;
static float YUVRGB07169 [256],YUVRGB03455 [256];
static float YUVRGB01779 [256] ;
int YUV2RGB( void* y_ in. void* u_ in. void* v_ in. void* rgb_ out,int W,int H)
{
unsigned char *b, *g, *r, *uBuff, *vBuff ;
unsigned char *y,*u,*v;
b = (unsigned char *)rgb_ out:
y = (unsigned char *)y_ in:
uBuff = (unsigned char *)u_ in;
vBuff = (unsigned char *)v_ in;
u = uBuff:
v = vBuff;
InitLookupTable();
float rt,gt, bt;
int i, j;
for (j = 0;j <H;j++)
{
for (i = 0: i < W; i++)
{
g = b + 1;
r = b + 2;
rt = (*y) + YUVRGB14075[*v];
gt =(*y) - YUVRGB07169[*v] - YUVRGB03455[*u];
bt = (*y) + YUVRGB01779[*u];
if (bt < 0)
bt = 0;
if (bt > 255)
bt = 255;
if (gt < 0)
gt = 0;
if (gt >255)
gt = 255;
if (rt< 0)
rt = 0;
if (rt > 255)
rt = 255;
*r = (unsigned char) rt ;
*g = (unsigned char)gt ;
*b= (unsigned char)bt ;
b+=3;
y++;
if (i % 2== 0 && j %2== 0)
{
u++;
v++;
}
}
}
return 0;
}
void InitLookupTable()
{
int i;
for (i = 0;i < 256; i++)
{
YUVRGB14075[i] = (float) 1.4075 * i ;
YUVRGB07169[i] = (float)0.7169* i ;
YUVRGB03455[i] = (float)0.3455 * i;
YUVRGB01779[i] = (float)0.1779 * i ;
}
}
打开与写入相关代码
errno_t err;
err = fopen_s(&yuvFile,yuvFileName, "rb");
if (err==0)
{
printf("The yuv file is %s\n", yuvFileName);
}
else
{
printf("yuv file can not be found \n");
}
//写入rgb文件
err = fopen_s(&rgbFile,rgbFileName, "wb");
if (err == 0)
{
printf("The rgb file is %s\n", rgbFileName);
}
else
{
printf("rgb file can not be found \n");
}
//rgb内存
while (fread(yBuf, 1, frameWidth * frameHeight, yuvFile)&&fread(uBuf, 1, frameWidth * frameHeight /4, yuvFile)&&fread(vBuf, 1, frameWidth * frameHeight /4, yuvFile))
{
//写入rgb
fwrite(rgbBuf, 1, frameWidth * frameHeight*3, rgbFile);
}
感想总结巴拉巴拉:
对于一个编程一直是很怕很怕而且基础很弱的人来说,这样的实验看要求总会是一头雾水,不知道是什么的慌张感。能够完成首先感谢老师一步一步给出的一个方向转换的讲解,能够对整个过程有了解,不惧怕,然后感谢小伙伴和网络上的宝藏资源,能够慢慢尝试,想必之后的实验也是费时费力,希望随着学习能够有思路,不逃避,有进步!