数据压缩实验1

来源:互联网 发布:淘宝有没有hm旗舰店 编辑:程序博客网 时间:2024/06/05 06:20

基本原理

彩色空间转化的公式及其分析

根据查询可以得到用 YUV计算得出RGB的公式

R=Y+1.4075(V−128)
G=Y−0.3455(U−128)−0.7169(V−128)
B=Y+1.779(U−128)
分析:根据

Cr=0.713(RY)

Cb=0.564(BY)转换并归一化

yuv文件存储方式是依次分别存完整的y、u、v、用三个指针分别指向,但是rgb文件在存储的过程中是按照bgrbgr的顺序存储的,所以在程序中将b的地址等于bmp之后rg分量可以用g = b + 1;r = b + 2;表示。


实验的流程分析

1、程序初始化(打开两个文件、定义变量和缓冲区等)

2、读取YUV文件,抽取YUV数据写入缓冲区 

3、调用YUV2RGB的函数实现YUVRGB数据的转换 

4、写RGB文件

5、程序收尾工作(关闭文件,释放缓冲区)
实验过程中一定要注意指针的使用,不能越界,开辟的指针空间在判断之后要记得释放

关键代码及其分析

main.cpp:

#include <stdio.h>

#include <stdlib.h>

#include <malloc.h>

#include “yuv2rgb.h”

定义int型

#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)

{

/* variables controlable from command line */

u_int frameWidth = 352;/* --width=<uint> */

u_int frameHeight = 240;/* --height=<uint> */

bool flip = TRUE;/* --flip */

unsigned int i;


/* internal variables */

char* rgbFileName = NULL;

char* yuvFileName = NULL;

/*两个文件指针*/

FILE* rgbFile = NULL;

FILE* yuvFile = NULL;

/*四个buffer,YUV*/

u_int8_t* yBuf = NULL;

u_int8_t* uBuf = NULL;

u_int8_t* vBuf = NULL;

u_int8_t* rgbBuf = NULL;

u_int32_t videoFramesWritten = 0;


/* begin process command line */

/* point to the specified file names */

通过项目-》属性-》配置属性-》调试 设置输入输出的文件名以及文件的宽高

yuvFileName = argv[1];

rgbFileName = argv[2];

frameWidth = atoi(argv[3]);

frameHeight = atoi(argv[4]);

/* open the RGB file */

yuvFile = fopen(yuvFileName, "rb");

if (yuvFile == NULL)

{

printf("cannot find yuv file\n");

exit(1);

}

else

{

printf("The input yuv file is %s\n", yuvFileName);

}


/* open the RAW file */

rgbFile = fopen(rgbFileName, "wb");

if (rgbFile == NULL)

{

printf("cannot find rgb file\n");

exit(1);

}

else

{

printf("The output rgb file is %s\n", rgbFileName);

}


/* get an input buffer for a frame */

开辟空间 注意输入的yuv文件中的ubuf和vbuf空间是ybuf的四分之一

yBuf = (u_int8_t*)malloc(frameWidth * frameHeight );

uBuf = (u_int8_t*)malloc(frameWidth * frameHeight/4);

vBuf = (u_int8_t*)malloc(frameWidth * frameHeight/4);


/* get the output buffers for a frame */

输出的rgb文件只需要一个指针,因此rgbbuf开辟的空间宽乘高乘三

rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight*3);


if (yBuf == NULL || uBuf == NULL || vBuf == NULL || rgbBuf == NULL)

{

printf("no enought memory\n");

exit(1);

}

当三个指针都读入且不为空的时候进入循环

while (fread(yBuf, 1, frameWidth * frameHeight , yuvFile) && fread(uBuf, 1, frameWidth * frameHeight /4, yuvFile)&&fread(vBuf, 1, frameWidth * frameHeight /4, yuvFile))

{

if (YUV2RGB(frameWidth, frameHeight, yBuf,uBuf,vBuf, rgbBuf, flip))

{

printf("error");

return 0;

}


fwrite(rgbBuf, 1, frameWidth * frameHeight*3, rgbFile);


printf("\r...%d", ++videoFramesWritten);

}


printf("\n%u %ux%u video frames written\n",

videoFramesWritten, frameWidth, frameHeight);


/* cleanup */

if (yuvFile != NULL)

{

fclose(yuvFile);

}

if (rgbFile != NULL)

{

fclose(rgbFile);

}

if (yBuf != NULL)

free(yBuf);

if (uBuf != NULL)

free(uBuf);

if (vBuf != NULL)

free(vBuf);

if (rgbBuf != NULL)

free(rgbBuf);


return(0);

}




/* This file contains RGB to YUV transformation functions.                */


#include "stdlib.h"

#include "yuv2rgb.h"


static float RGBYUV14075[256], RGBYUV03455[256], RGBYUV07169[256];

static float RGBYUV17790[256];



/************************************************************************

*

*  int RGB2YUV (int x_dim, int y_dim, void *bmp, YUV *yuv)

*

* Purpose :It takes a 24-bit RGB bitmap and convert it into

* YUV (4:2:0) format

*

*  Input : x_dimthe x dimension of the bitmap

* y_dimthe y dimension of the bitmap

* bmppointer to the buffer of the bitmap

* yuvpointer to the YUV structure

*

*  Output : 0OK

* 1wrong dimension

* 2memory allocation error

*

* Side Effect :

* None

*

* Date :09/28/2000

*

*  Contacts:

*

*  Adam Li

*

*  DivX Advance Research Center <darc@projectmayo.com>

*

************************************************************************/


int YUV2RGB(int x_dim, int y_dim, void *yin,void *uin,void *vin, void *bmp , int flip)

{

static int init_done = 0;

long i, j, size;

unsigned char *r, *g, *b;

unsigned char *y, *u, *v;

float r1, g1, b1;

unsigned char *pu1,*pu2,*pv1,*pv2,*psu,*psv;

unsigned char *y_buffer,*u_buffer,*v_buffer;

unsigned char *up_u_buf, *up_v_buf;


if (init_done == 0)

{

InitLookupTable();

init_done = 1;

}

y_buffer =(unsigned char*) yin;

u_buffer = (unsigned char*)uin;

v_buffer = (unsigned char*)vin;

// check to see if x_dim and y_dim are divisible by 2

if ((x_dim % 2) || (y_dim % 2)) return 1;

size = x_dim * y_dim;


// allocate memory

上采样之后得到的指针空间大小和y是一样的

up_u_buf = (unsigned char *)malloc(size*sizeof(unsigned char));

up_v_buf = (unsigned char *)malloc(size*sizeof(unsigned char));

if (!(up_u_buf && up_v_buf))

{

if (up_u_buf) free(up_u_buf);

if (up_v_buf) free(up_v_buf);

return 2;

}


y = y_buffer;

u = up_u_buf;

v = up_v_buf;

b = (unsigned char*)bmp;


//upsample UV

根据RGB2YUV程序中的下采样指针地址的赋值,此处没有做过多调整,上采样的过程四个像素点YU分量分别赋相同的值

for (j = 0; j < y_dim/2; j++)

{

psu = u_buffer + j * x_dim / 2;

psv = v_buffer + j * x_dim / 2;

pu1 = up_u_buf + 2 * j * x_dim;

pu2 = up_u_buf + (2 * j + 1) * x_dim;

pv1 = up_v_buf + 2 * j * x_dim;

pv2 = up_v_buf + (2 * j + 1) * x_dim;

for (i = 0; i < x_dim / 2; i++)

{

*pu1 = *psu;

*(pu1+1) = *psu;(此处如果用*(pu1++)下面用pu1++有错误)

*pu2 = *psu;

*(pu2+1) = *psu;

*pv1 = *psv;

*(pv1+1) = *psv;

*pv2 = *psv;

*(pv2+1) = *psv;

psu++;

psv++;

pu1 +=2;

pu2 +=2;

pv1 +=2;

pv2 +=2;

}


}



// convert RGB to YUV


为了防止色彩溢出用一个float型的中间变量控制

 

for (i = 0; i < size; i++)

{

g = b + 1;

r = b + 2;

r1 = *y + RGBYUV14075[*v ];

g1 = *y - RGBYUV03455[*u ] - RGBYUV07169[*v];

b1 = *y + RGBYUV17790[*u ];

if (r1 < 0) r1 = 0;

if (r1 > 255) r1 = 255;

if (g1 < 0) g1 = 0;

if (g1 > 255) g1 = 255;

if (b1 < 0) b1 = 0;

if (b1 > 255) b1 = 255;

*r = (unsigned char)r1;

*g = (unsigned char)g1;

*b = (unsigned char)b1;

b += 3;


y++;

u++;

v++;

}

if (up_u_buf != NULL)free(up_u_buf);

if (up_v_buf != NULL)free(up_v_buf);

return 0;

}


此处如果用float1.4075*i有错

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);

}




实验结果及分析




   






经过不同输入文件的对比,我们可以看出来,通过yuv转换到rgb再转换到yuv的过程中,yuv文件基本上没有太大的变化,可以证明程序的正确性,这说明rgb文件的确和yuv文件存在一定程度上的差别。         

结论

经过分析,可以看得出来,转换成rgb格式的yuv文件存在一定程度上的色彩失真。


0 0
原创粉丝点击