使用C++实现YUV格式图像与RGB格式图像之间相互转换
一、RGB与YUV转换公式
1、RGB转YUV
1)RGB转换亮度与色差信号公试:
Y=0.299R+0.587G+0.114B
R-Y=0.701R-0.587G-0.114B
B-Y=-0.299R-0.587G+0.866B
2)归一化为YUV的转化公试为:
Y=0.299R+0.587G+0.114B
U=-0.168R-0.332G+0.5B
V=0.5R-0.419G-0.081B
2、YUV转RGB
根据RGB转YUV转换公式,我们可以计算出YUV转化为RGB的公试:
R=Y+1.40 (V-28)
G=Y-0.344 (U-128)-0.714(V-128)
B=Y+1.772*(U-128)
二、利用命令参数实现读取文件的简单化安全化
通过选择“项目”-“yuv2rgb属性”进入yuv2rgb属性页
在属性页中选择“配置属性”-“调试”进入调试器界面
在命令参数中按顺序依次输入值(文件名称、参数等)并以“ ”(空格)隔开,这些值会依次排放在argv[1]-argv[n]之中,需要调用的时候直接赋值即可:
yuvFileName = argv[1];
rgbFileName = argv[2];
frameWidth = atoi(argv[3]);
frameHeight = atoi(argv[4]);
并在工作目录选择文件所在位置即可并通过已下代码即可使文件读取更加安全,文件路径不会再在代码中展现:
yuvFile = fopen(yuvFileName, "rb");
rgbFile = fopen(rgbFileName, "wb");
三、使用C++实现YUV格式图像转换为RGB格式图像
实现这一共功能一共分为三个部分,主体实现(main1.cpp),yuv到rgb的转换(yuv2rgb.cpp),yuv到rgb的头文件(yuv2rgb.h);
其中最为重要的是yuv到rgb转换功能的实现,即yuv2rgb.cpp,因此下面我先简述yuv2rgb.cpp的具体实验过程
(一)、YUV格式到RGB格式的转换(yuv2rgb.cpp)
1、实现YUV转RGB公式
因为图像大小为256*256,若在转换时对每个像素以此进行转换公式的计算,则计算量过大,所以可以先建立一个转换公式,计算0-255像数值的转换,并将其存在数组中,这样在后续的使用中可以直接调用其对应的值不用再一一计算,大大提高了程序运行效率。根据转换公试,具体实现如下:
void InitLookupTable()
{
int i;
for (i = 0; i < 256; i++) RGBYUV14075[i] = (float)1.4075 * (i-128);
for (i = 0; i < 256; i++) RGBYUV03455[i] = (float)0.3455 * (i - 128);
for (i = 0; i < 256; i++) RGBYUV07169[i] = (float)0.7169 * (i - 128);
for (i = 0; i < 256; i++) RGBYUV17790[i] = (float)1.7790 * (i - 128);
}
2、图像数据的读入
因为YUV格式图像分辨率为256* 256,所以Y分配空间为256* 256,U、V分配空间为256*256/4:
y_buffer = (unsigned char*)malloc(size* sizeof(unsigned char));
u_buffer = (unsigned char*)malloc(size* sizeof(unsigned char) / 4);
v_buffer = (unsigned char*)malloc(size* sizeof(unsigned char) / 4);
sub_u_buf = (unsigned char*)malloc(size* sizeof(unsigned char));
sub_v_buf = (unsigned char*)malloc(size* sizeof(unsigned char));
yuv_buffer = (unsigned char*)bmp;
y = y_buffer;
u = u_buffer;
v = v_buffer;
其中y_buffer、u_buffer、v_buffer为存放Y、U、V数据的指针,y,u,v为读入数据的中间过渡传递指针;
因为RGB格式图像的R、G、B分量都为256256大小,所以需要将,原本为256256/4的U、V分量扩大以此才方便计算,所以设置sub_u_buf、sub_v_buf两个为256*256大小的指针以此来进行扩充存放。
因为YUV格式图像为按照全部像素Y数据块、U数据块、V数据块依次存放,且为4:2:0采样,所以读取方式为YYYY…,U…,V…:
for (i = 0; i < size; i ++)
{
*y = *(yuv_buffer + i);
y++;
}
for (i = size; i < size * 5 / 4; i++)
{
*u = *(yuv_buffer + i);
u++;
}
for (i = size * 5 / 4; i < size * 3 / 2; i ++)
{
*v = *(yuv_buffer + i);
v++;
}
3、将U、V分量扩充到256*256
因为RGB格式图像的R、G、B分量都为256256大小,所以需要将原本为256256/4的U、V分量扩大以此才方便计算,这里设置sub_u_buf、sub_v_buf两个为256*256大小的指针以此来进行扩充存放。
我选用将U、V的值直接分配给他最近邻的4个值的方法(如图所示,将原本左上角位置的a直接赋值给其正下方,右方,与右下方三个值
a | a |
---|---|
a | a |
)以此来实现对U、V分量的扩充。具体实现如下:
for (i = 0; i < y_dim / 2; i ++)
{
pu1 = sub_u_buf + i * 2 * x_dim;
pu2 = sub_u_buf + (i * 2 + 1) * x_dim;
pv1 = sub_v_buf + i * 2 * x_dim;
pv2 = sub_v_buf + (i * 2 + 1) * x_dim;
for (j = 0; j < x_dim / 2;j++)
{
*pu1 = *(u_buffer + j + i * x_dim / 2);
*pu2 = *pu1;
pu1++;
pu2++;
*pu1 = *(u_buffer + j + i * x_dim / 2);
*pu2 = *pu1;
pu1++;
pu2++;
*pv1 = *(v_buffer + j + i * x_dim / 2);
*pv2 = *pv1;
pv1++;
pv2++;
*pv1 = *(v_buffer + j + i * x_dim / 2);
*pv2 = *pv1;
pv1++;
pv2++;
}
}
4、将YUV转化为RGB
因为所用的读图工具(gbmp)为倒着读图中的数据,所以需要设计两种方式的转化,来实现正数据存放与倒数据存放;
并且因为在上面公式数组中计算存放的数值为“float”型,而传入图像所需的数据是“unsigned char”型,所以将“float”型数据强制转换为“unsigned char”是可能会出现数据溢出(通过转换公式得到的R、G、B分量值可能得到负值或大于255的值)所以需要将溢出的值规定为不溢出的值,我将负值=0,大于255的值=255。这样既可解决数值溢出问题,所以需要另设“float”类型参数sub_r、sub_g、sub_b来作为中间参数;
具体实现方法如下:
if (flip)
{
for (i = 0; i < size; i++)
{
sub_r = *(y_buffer+i) + RGBYUV14075[*(sub_v_buf+i)];
sub_g = *(y_buffer+i) - RGBYUV03455[*(sub_u_buf+i)] - RGBYUV07169[*(sub_v_buf+i)];
sub_b = *(y_buffer+i) + RGBYUV17790[*(sub_u_buf+i)];
if (sub_r < 0) sub_r = 0;
if (sub_r > 255) sub_r = 255;
if (sub_g < 0) sub_g = 0;
if (sub_g > 255) sub_g = 255;
if (sub_b < 0) sub_b = 0;
if (sub_b > 255) sub_b = 255;
*r = (unsigned char)sub_r;
*g = (unsigned char)sub_g;
*b = (unsigned char)sub_b;
r++;
g++;
b++;
}
}
else {
for (j = 0; j < y_dim; j++)
{
psy = y_buffer + (y_dim - 1 - j) * x_dim;
psu = sub_u_buf + (y_dim - 1 - j) * x_dim;
psv = sub_v_buf+ (y_dim - 1 - j) * x_dim;
for (i = 0; i < x_dim; i++)
{
sub_r = *(psy+i) + RGBYUV14075[*(psv+i)];
sub_g = *(psy+i) - RGBYUV03455[*(psu+i)]- RGBYUV07169[*(psv+i)];
sub_b = *(psy+i) + RGBYUV17790[*(psu+i)];
if (sub_r < 0) sub_r = 0;
if (sub_r > 255) sub_r = 255;
if (sub_g < 0) sub_g = 0;
if (sub_g > 255) sub_g = 255;
if (sub_b < 0) sub_b = 0;
if (sub_b > 255) sub_b = 255;
*r = (unsigned char)(sub_r);
*g = (unsigned char)(sub_g);
*b = (unsigned char)(sub_b);
r++;
g++;
b++;
}
}
}
(二)主函数(main.cpp)
主函数调用YUV2RGB函数功能即可算出R、G、B的值,所以在主函数中,我们需要关注的是如何将R、G、B三分量的值传入RGB格式文件中。
RGB格式文件按每个像素BGR分量以此存储,所以读取方式为b,g,r,b,g,r…;因此我们需要将计算得出的RGB值以此进行传入;
具体实现如下:
for (i = 0; i < frameWidth * frameHeight; i++)
{
fwrite(bBuf+i, 1, 1, rgbFile);
fwrite(gBuf+i, 1, 1, rgbFile);
fwrite(rBuf+i, 1, 1, rgbFile);
}
(三)结果演示
原图像:
因为如上文所说,读图软件(bgmp)为倒着读图像,所以结果分两种情况演示
当flip = TRUE时:输出图像为倒像,并且因为数值溢出后经过调整,使颜色也略微有偏差。
当flip = FALSE时:输出图像为正像,并且因为数值溢出后经过调整,使颜色也略微有偏差。
(四)整体代码
1、main:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "yuv2rgb.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 = 0;
u_int frameHeight = 0;
bool flip = FALSE;
unsigned int i;
char* rgbFileName = NULL;
char* yuvFileName = NULL;
FILE* rgbFile = NULL;
FILE* yuvFile = NULL;
u_int8_t* yuvBuf = NULL;
u_int8_t* rBuf = NULL;
u_int8_t* gBuf = NULL;
u_int8_t* bBuf = NULL;
u_int32_t videoFramesWritten = 0;
yuvFileName = argv[1];
rgbFileName = argv[2];
frameWidth = atoi(argv[3]);
frameHeight = atoi(argv[4]);
yuvFile = fopen(yuvFileName, "rb");
if (yuvFile == NULL)
{
printf("cannot find yuv file\n");
exit(1);
}
else
{
printf("The input rgb file is %s\n", yuvFileName);
}
rgbFile = fopen(rgbFileName, "wb");
if (rgbFile == NULL)
{
printf("cannot find rgb file\n");
exit(1);
}
else
{
printf("The output yuv file is %s\n", rgbFileName);
}
yuvBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3 / 2);
rBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
gBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
bBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
if (yuvBuf == NULL || rBuf == NULL || gBuf == NULL || bBuf == NULL)
{
printf("no enought memory\n");
exit(1);
}
while (fread(yuvBuf, 1, frameWidth*frameHeight* 3/2, yuvFile))
{
if (YUV2RGB(frameWidth, frameHeight, yuvBuf, rBuf, gBuf, bBuf, flip))
{
printf("error");
return 0;
}
for (i = 0; i < frameWidth * frameHeight; i++)
{
fwrite(bBuf+i, 1, 1, rgbFile);
fwrite(gBuf+i, 1, 1, rgbFile);
fwrite(rBuf+i, 1, 1, rgbFile);
}
printf("\r...%d", ++videoFramesWritten);
}
printf("\n%u %ux%u video frames written\n",
videoFramesWritten, frameWidth, frameHeight);
fclose(rgbFile);
fclose(yuvFile);
return(0);
}
2、yuv2rgb.cpp
#include "stdlib.h"
#include "yuv2rgb.h"
static float RGBYUV14075[256], RGBYUV03455[256], RGBYUV07169[256], RGBYUV17790[256];
int YUV2RGB(int x_dim, int y_dim, void* bmp, void* r_out, void* g_out, void* b_out, int flip)
{
static int init_done = 0;
long i, j, size;
unsigned char* r, * g, * b;
unsigned char* y, * u, * v;
unsigned char* pu1, * pu2,* pv1, * pv2,* psu,* psv,* psy;
unsigned char* y_buffer, *u_buffer, *v_buffer, *yuv_buffer;
unsigned char *sub_u_buf, *sub_v_buf;
float sub_r,sub_g,sub_b;
if (init_done == 0)
{
InitLookupTable();
init_done = 1;
}
if ((x_dim % 2) || (y_dim % 2)) return 1;
size = x_dim * y_dim;
y_buffer = (unsigned char*)malloc(size* sizeof(unsigned char));
u_buffer = (unsigned char*)malloc(size* sizeof(unsigned char) / 4);
v_buffer = (unsigned char*)malloc(size* sizeof(unsigned char) / 4);
sub_u_buf = (unsigned char*)malloc(size* sizeof(unsigned char));
sub_v_buf = (unsigned char*)malloc(size* sizeof(unsigned char));
yuv_buffer = (unsigned char*)bmp;
y = y_buffer;
u = u_buffer;
v = v_buffer;
r = (unsigned char*)r_out;
g = (unsigned char*)g_out;
b = (unsigned char*)b_out;
for (i = 0; i < size; i ++)
{
*y = *(yuv_buffer + i);
y++;
}
for (i = size; i < size * 5 / 4; i++)
{
*u = *(yuv_buffer + i);
u++;
}
for (i = size * 5 / 4; i < size * 3 / 2; i ++)
{
*v = *(yuv_buffer + i);
v++;
}
for (i = 0; i < y_dim / 2; i ++)
{
pu1 = sub_u_buf + i * 2 * x_dim;
pu2 = sub_u_buf + (i * 2 + 1) * x_dim;
pv1 = sub_v_buf + i * 2 * x_dim;
pv2 = sub_v_buf + (i * 2 + 1) * x_dim;
for (j = 0; j < x_dim / 2;j++)
{
*pu1 = *(u_buffer + j + i * x_dim / 2);
*pu2 = *pu1;
pu1++;
pu2++;
*pu1 = *(u_buffer + j + i * x_dim / 2);
*pu2 = *pu1;
pu1++;
pu2++;
*pv1 = *(v_buffer + j + i * x_dim / 2);
*pv2 = *pv1;
pv1++;
pv2++;
*pv1 = *(v_buffer + j + i * x_dim / 2);
*pv2 = *pv1;
pv1++;
pv2++;
}
}
if (flip)
{
for (i = 0; i < size; i++)
{
sub_r = *(y_buffer+i) + RGBYUV14075[*(sub_v_buf+i)];
sub_g = *(y_buffer+i) - RGBYUV03455[*(sub_u_buf+i)] - RGBYUV07169[*(sub_v_buf+i)];
sub_b = *(y_buffer+i) + RGBYUV17790[*(sub_u_buf+i)];
if (sub_r < 0) sub_r = 0;
if (sub_r > 255) sub_r = 255;
if (sub_g < 0) sub_g = 0;
if (sub_g > 255) sub_g = 255;
if (sub_b < 0) sub_b = 0;
if (sub_b > 255) sub_b = 255;
*r = (unsigned char)sub_r;
*g = (unsigned char)sub_g;
*b = (unsigned char)sub_b;
r++;
g++;
b++;
}
}
else {
for (j = 0; j < y_dim; j++)
{
psy = y_buffer + (y_dim - 1 - j) * x_dim;
psu = sub_u_buf + (y_dim - 1 - j) * x_dim;
psv = sub_v_buf+ (y_dim - 1 - j) * x_dim;
for (i = 0; i < x_dim; i++)
{
sub_r = *(psy+i) + RGBYUV14075[*(psv+i)];
sub_g = *(psy+i) - RGBYUV03455[*(psu+i)]- RGBYUV07169[*(psv+i)];
sub_b = *(psy+i) + RGBYUV17790[*(psu+i)];
if (sub_r < 0) sub_r = 0;
if (sub_r > 255) sub_r = 255;
if (sub_g < 0) sub_g = 0;
if (sub_g > 255) sub_g = 255;
if (sub_b < 0) sub_b = 0;
if (sub_b > 255) sub_b = 255;
*r = (unsigned char)(sub_r);
*g = (unsigned char)(sub_g);
*b = (unsigned char)(sub_b);
r++;
g++;
b++;
}
}
}
free(y_buffer);
free(u_buffer);
free(v_buffer);
free(sub_u_buf);
free(sub_v_buf);
return 0;
}
void InitLookupTable()
{
int i;
for (i = 0; i < 256; i++) RGBYUV14075[i] = (float)1.4075 * (i-128);
for (i = 0; i < 256; i++) RGBYUV03455[i] = (float)0.3455 * (i - 128);
for (i = 0; i < 256; i++) RGBYUV07169[i] = (float)0.7169 * (i - 128);
for (i = 0; i < 256; i++) RGBYUV17790[i] = (float)1.7790 * (i - 128);
}
3、yuv2rgb.h
int YUV2RGB(int x_dim, int y_dim, void* bmp, void* r_out, void* g_out, void* b_out, int flip);
void InitLookupTable();
四、使用C++实现RGB格式图像转换为YUV格式图像
因为和YUV格式图像转RGB格式图像思路相近,所以这里只给出完整代码:
1、main.cpp
#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;
u_int frameHeight = 240;
bool flip = TRUE;
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);
}
2、rgb2yuv.cpp
#include "stdlib.h"
#include "rgb2yuv.h"
static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
static float RGBYUV01684[256], RGBYUV03316[256];
static float RGBYUV04187[256], RGBYUV00813[256];
int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip)
{
static int init_done = 0;
long i, j, size;
unsigned char *r, *g, *b;
unsigned char *y, *u, *v;
unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv;
unsigned char *y_buffer, *u_buffer, *v_buffer;
unsigned char *sub_u_buf, *sub_v_buf;
if (init_done == 0)
{
InitLookupTable();
init_done = 1;
}
if ((x_dim % 2) || (y_dim % 2)) return 1;
size = x_dim * y_dim;
y_buffer = (unsigned char *)y_out;
sub_u_buf = (unsigned char *)u_out;
sub_v_buf = (unsigned char *)v_out;
u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char));
if (!(u_buffer && v_buffer))
{
if (u_buffer) free(u_buffer);
if (v_buffer) free(v_buffer);
return 2;
}
b = (unsigned char *)bmp;
y = y_buffer;
u = u_buffer;
v = v_buffer;
if (!flip) {
for (j = 0; j < y_dim; j ++)
{
y = y_buffer + (y_dim - j - 1) * x_dim;
u = u_buffer + (y_dim - j - 1) * x_dim;
v = v_buffer + (y_dim - j - 1) * x_dim;
for (i = 0; i < x_dim; i ++) {
g = b + 1;
r = b + 2;
*y = (unsigned char)( RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
*u = (unsigned char)(- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2 + 128);
*v = (unsigned char)( (*r)/2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
b += 3;
y ++;
u ++;
v ++;
}
}
} else {
for (i = 0; i < size; i++)
{
g = b + 1;
r = b + 2;
*y = (unsigned char)( RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
*u = (unsigned char)(- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2 + 128);
*v = (unsigned char)( (*r)/2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
b += 3;
y ++;
u ++;
v ++;
}
}
for (j = 0; j < y_dim/2; j ++)
{
psu = sub_u_buf + j * x_dim / 2;
psv = sub_v_buf + j * x_dim / 2;
pu1 = u_buffer + 2 * j * x_dim;
pu2 = u_buffer + (2 * j + 1) * x_dim;
pv1 = v_buffer + 2 * j * x_dim;
pv2 = v_buffer + (2 * j + 1) * x_dim;
for (i = 0; i < x_dim/2; i ++)
{
*psu = (*pu1 + *(pu1+1) + *pu2 + *(pu2+1)) / 4;
*psv = (*pv1 + *(pv1+1) + *pv2 + *(pv2+1)) / 4;
psu ++;
psv ++;
pu1 += 2;
pu2 += 2;
pv1 += 2;
pv2 += 2;
}
}
free(u_buffer);
free(v_buffer);
return 0;
}
void InitLookupTable()
{
int i;
for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;
for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;
for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;
for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;
for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;
for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;
for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;
}
3、rgb2yuv.h
int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip);
void InitLookupTable();
4、结果呈现
原图:
输出图像:颜色因为整理数值溢出问题所以略有区别
五、归纳总结
通过此次实验熟悉了两种图像格式之间的转换,并且熟悉巩固了C++语言的使用,为后续进一步学习数据压缩打下了基础。