您的位置:首页 > 其它

数据压缩实验二 图像文件的读写和转换(bmp转yuv)

2017-03-16 18:06 696 查看

一、实验原理

图像存储时一般由两部分组成:图像说明部分和图 像数据部分

图像说明部分:图像的格式、深度、高度、宽度、调色板、 压缩方法等

图像数据部分:描述图像每个像素的数据

1.BMP图像文件格式

位图文件(Bitmap-File,BMP)格式是Windows采 用的图像文件存储格式,在Windows环境下运行的 所有图像处理软件都支持这种格式。BMP位图文件 默认的文件扩展名是bmp或者dib。

BMP文件大体上分为四个部分:

位图文件头BITMAPFILEHEADER
位图信息头BITMAPINFOHEADER
调色板Palette
实际的位图数据ImageData
对于一种文件的格式,C语言中往往以结构体的方式描述,因此注意工程中的结构体是十分重要的。

(1)位图头文件数据结构

typedef struct tagBITMAPFILEHEADER
{
WORD bfType; /* 说明文件的类型 */
DWORD bfSize; /* 说明文件的大小,用字节为单位 注意字节序*/
WORD bfReserved1; /* 保留,设置为0 */
WORD bfReserved2; /* 保留,设置为0 */
DWORD bfOffBits; /* 说明从BITMAPFILEHEADER结构开始到实际的图像数据之间的字节偏移量 */
} BITMAPFILEHEADER;


(2)位图信息数据结构

typedef struct tagBITMAPINFOHEADER
{
DWORD biSize; /* 说明结构体所需字节数 */
LONG biWidth; /* 以像素为单位说明图像的宽度 */
LONG biHeight; /* 以像素为单位说明图像的高度 */
WORD biPlanes; /* 说明位面数,必须为1 */
WORD biBitCount; /* 说明位数/像素,1、2、4、8、24 */
DWORD biCompression; /* 说明图像是否压缩及压缩类型BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS */
DWORD biSizeImage; /* 以字节为单位说明图像大小,必须是4的整数倍*/
LONG biXPelsPerMeter; /*目标设备的水平分辨率,像素/米 */
LONG biYPelsPerMeter; /*目标设备的垂直分辨率,像素/米 */
DWORD biClrUsed; /* 说明图像实际用到的颜色数,如果为0,则颜色数为2的biBitCount次方 */

4000
DWORD biClrImportant; /*说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要。*/
} BITMAPINFOHEADER;


(3)调色板

调色板实际上是一个数组,它所包含的元素与位图 所具有的颜色数相同,决定于biClrUsed和biBitCount字 段。数组中每个元素的类型是一个RGBQUAD结构。真 彩色无调色板部分。

typedef struct tagRGBQUAD
{
BYTE rgbBlue; /*指定蓝色分量*/
BYTE rgbGreen; /*指定绿色分量*/
BYTE rgbRed; /*指定红色分量*/
BYTE rgbReserved; /*保留,指定为0*/
} RGBQUAD;


(4)图像数据字节阵列:即位图数据

紧跟在调色板之后的是图像数据字节阵列。对于用到调 色板的位图,图象数据就是该象素颜色在调色板中的索引值 (逻辑色)。对于真彩色图,图象数据就是实际的R、G、B 值。

2.需要注意的地方

(1)DWORD 对齐

图像的每一扫描行由表示图像像素的连续的字节组成,每一行的字节数取决于图像的颜色数目和用像素表示的图像宽

度。规定每一扫描行的字节数必需是4的整倍数,也就是DWORD对齐的。写入位图文件数据时,如果图像每行像素字节总数[宽 X biBiCount % 8 != 0 ],系统会自动在每行最后填充若干0值使满足整数字节,接着,如果[每行像素字节数 % 4 != 0 ],系统会自动在每行最后填充若干字节0值使满足DWORD对齐。所以我们对位图加载处理时要注意判断每行数据是否有0值填充,若有0值填充则从位图中读取数据的过程中要注意指针偏移量和即时跳转。

(2)自下而上扫描

扫描行是由底向上存储的,这就是说,阵列中的第一个字节表示位图左下角的像素,而最后一个字节表示位图右上角的像素。(只针对于倒向DIB,如果是正向DIB,则扫描行是由顶向下存储)

(3)字节序

计算机系统存储数据采用的字节序有两种:小尾字节序(Little Endian)和大尾字节序(Big Endian)。以Intel处理器为代表大多数采用小端字节序,”低位在前高位在后“既地址低位存储值的低位,地址高位存储值的高位;以Motorola处理器为代表大多数使用大端字节序,”高位在前低位在后“即地址低位存储值的高位,地址高位存储值的低位。BMP文件中仅除了文件头中文件类型WORD bfType为大端字节序,剩余结构体内的定义均是小端字节序。

(4)掩码组

调色板信息中指示了RGB比特位的掩码组信息。因为图像深度可选为1、4、8、16、24、32bit,所以不同深度的RGB比特位自然不同。

以bmp位图中使用16bit为例,位运算的图示:



若读入的BMP位图的biBiCount为8bit或更小,类似的需要位的移位、与操作。

再以2bit图像举例,其数据块中的第一个字节,对应着第一个像素的索引值为:b’xx zz zz zz,其中只有头两位包含该像素的索引信息,而后六位为其他像素的索引信息。这时候需要与b’11 00 00 00=0xC0相与,再进行6位右移,得到b’00 00 00 xx=index,这便是其对应的索引值,代入pRGB[index]获得其对应的RGB分量值。

当处理像素是第二个像素是,其对应的索引值应为该字节中的第五第六位,即b’zz xx zz zz,这时候掩码值也相应跟着位移,遂引入turn–掩码位移变量,turn可用作循环判断用,当turn为零时——说明该字节中所有像素信息已读取完,可以结束循环,进行下一个字节的读取。

同时,应注意到右移的位数也发生了变换,引入shiftcnt变量,用于不同像素点需位移的长度。每进行一次像素数据读取后,shiftcnt++,因为下一个像素(不是该字节最后一个像素时)需要位移的位数减少了shift*biBitCount个。

二、实验流程

(1)初始化:打开文件,定义变量建立缓冲区

(2)解析BMP文件,抽取或生成RGB数据写入缓冲区

(3)调用RGB2YUV函数进行数据转换

(4)写入YUV文件,关闭文件,释放缓冲区



三、实验具体算法代码

1.BMP2YUV.h

#ifndef BMP2YUV_H_
#define BMP2YUV_H_

//define mask struct
typedef struct bit32Mask
{
unsigned int rgbRed;
unsigned int rgbGreen;
unsigned int rgbBlue;
unsigned int reserved;
}Mas32;
typedef struct bit16Mask
{
unsigned int rgbRed;
unsigned int rgbGreen;
unsigned int rgbBlue;
}Mas16;

int BMP2RGB32bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *mask);
int BMP2RGB24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf);
int BMP2RGB16bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf,void *mask);
int BMP2RGBNOT24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *pRGB);
int RGB2YUV(int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip);
void InitLookupTable();
void adjust(unsigned char *b, unsigned char *g, unsigned char *r, unsigned char *y, unsigned char *u, unsigned char  *v);
#endif


2.main.c

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <math.h>
#include "bmp2yuv.h"

#define u_int8_t    unsigned __int8
#define u_int       unsigned __int32
#define u_int32_t   unsigned __int32

int main(int argc,char **argv)
{
int count;
BITMAPFILEHEADER File_header;
BITMAPINFOHEADER Info_header;
RGBQUAD *pRGB = NULL;
FILE* bmp = NULL;
FILE* yuvFile = NULL;
Mas16 *mask16 = NULL;
Mas32 *mask32 = NULL;

u_int8_t* yBuf = NULL;
u_int8_t* uBuf = NULL;
u_int8_t* vBuf = NULL;
u_int8_t* rgbBuf = NULL;
u_int8_t* bmpBuf = NULL;
u_int8_t* mask = NULL;
u_int frameWidth;       /* --width=<uint> */
u_int frameHeight;
u_int bitcount;
u_int py;
u_int m;
u_int8_t i;
int sum = 0;

char bmpf[][50] = { "park.bmp", "tree.bmp", "girlstwo.bmp", "02.bmp", "bea.bmp", "street.bmp" };
char yuvname[50] = "CometoYUV.yuv";
FILE *yuv=NULL;
int framenumber;

/* build the RAW file */
fopen_s(&yuv, yuvname, "wb+");
if (yuv == NULL)
{
printf("Fail to Build yuv file\n");
exit(0);
}
else
{
printf("The output rgb file is %s\n", yuvname);
printf("\n");
printf("-------------------------------------------------------------------------\n");
}

for (i = 0; i<6; i++)
{

count = 0;
framenumber = atoi(argv[i + 1]);
//open the bmp file
fopen_s(&bmp, bmpf[i], "rb");
if (!bmp)
{
printf("cannot find the specific file %s:\n", bmpf[i]);
exit(0);
}
else
{
printf("The input bmp file:   %s\n", bmpf[i]);
}
if (!framenumber)
{
printf("\n写入帧数:0\n");
continue;
}
else
{
if (fread(&File_header, sizeof(BITMAPFILEHEADER), 1, bmp) != 1)
{
printf("read file header error!");
exit(0);
}
if (File_header.bfType != 0x4D42)
{
printf("Not bmp file!");
exit(0);
}
//printf("this is a 0x%04X:\n", File_header.bfType);
if (fread(&Info_header, sizeof(BITMAPINFOHEADER), 1, bmp) != 1)
{
printf("read info header error!");
exit(0);
}
//  end read header
frameWidth = Info_header.biWidth;           /* --width=<uint> */
frameHeight = Info_header.biHeight;
py = File_header.bfOffBits;
bitcount = Info_header.biBitCount;
/* get an output buffer for a frame */
if ((frameWidth*bitcount % 8 == 0) && (frameWidth*bitcount / 8 % 4 == 0))//DWORD 对齐
{
yBuf = (u_int8_t*)malloc(frameWidth * frameHeight);
uBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);
vBuf = (u_int8_t*)malloc((frameWidth * frameHeight) / 4);

/* get an input buffer for a frame */
bmpBuf = (u_int8_t*)malloc(frameWidth * frameHeight * bitcount / 8);

/* get an output buffer for a frame */
rgbBuf = (u_int8_t*)malloc(frameWidth * frameHeight * 3);

if (rgbBuf == NULL || yBuf == NULL || uBuf == NULL || vBuf == NULL || bmpBuf == NULL)
{
printf("no enought memory\n");
exit(1);
}

////////////////////////////////BMP 2 RGB
while (framenumber)
{
fseek(bmp, py, SEEK_SET);
if (!fread(bmpBuf, 1, frameWidth * frameHeight * bitcount / 8, bmp))
{
printf("the image has problems!");
return 0;
}
if (bitcount == 32)
{
if (Info_header.biCompression==0)
{
if (BMP2RGB32bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf,0))
{
printf("32bit BMP2RGB program runs error!");
return 0;
}
}
else if (Info_header.biCompression == 3)
{
//取掩码组
m = 4*4;
mask32 = (Mas32*)malloc(sizeof(Mas32));
fseek(bmp, sizeof(BITMAPFILEHEADER) + Info_header.biSize - m, SEEK_SET);
fread(mask32, sizeof(Mas32),1, bmp);
if (BMP2RGB32bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, mask32))
{
printf("32bit BMP2RGB program runs error!");
return 0;
}
}
}
else if (bitcount == 24)
{//真彩位图
if (BMP2RGB24bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf))
{
printf("24bit BMP2RGB program runs error!");
return 0;
}
}
else if (bitcount == 16)
{
//16bit BMP RGB比特位根据biCompression确定
if (Info_header.biCompression == 0)//555
{
if (BMP2RGB16bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, 0))
{
printf("16bit BMP2RGB program runs error!");
return 0;
}
}
else if (Info_header.biCompression == 3)
{
//取掩码组
m = 4 * 3;
mask16 = (Mas16*)malloc(sizeof(Mas16));
fseek(bmp, py-m, SEEK_SET);
fread(mask16, 1, m, bmp);
if (BMP2RGB16bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, mask16))
{
printf("16bit BMP2RGB program runs error!");
return 0;
}
}
}
else
{
if ((py - sizeof(BITMAPFILEHEADER) - Info_header.biSize) == sizeof(RGBQUAD)*pow(2, (double)bitcount))
{//1、2、4、8 bit 有调色板部分
m = (unsigned int)pow(2, (double)bitcount);
pRGB = (RGBQUAD *)malloc(sizeof(RGBQUAD)*m);
fseek(bmp, sizeof(BITMAPFILEHEADER) + Info_header.biSize, SEEK_SET);
fread(pRGB, sizeof(RGBQUAD), m, bmp);
if (BMP2RGBNOT24bit(bitcount, frameWidth, frameHeight, bmpBuf, rgbBuf, pRGB))
{
printf("BMP 2 RGB program runs error!");
return 0;
}
}
}
/////////////////////////////RGB2YUV
if (RGB2YUV(frameWidth, frameHeight, rgbBuf, yBuf, uBuf, vBuf, 0/*flip=0*/))//bmp图像格式从最后一行起逐行扫描
{
printf("RGB2YUV program runs error!");
return 0;
}
fwrite(yBuf, 1, frameWidth * frameHeight, yuv);
fwrite(uBuf, 1, (frameWidth * frameHeight) / 4, yuv);
fwrite(vBuf, 1, (frameWidth * frameHeight) / 4, yuv);

printf("\r...%d", ++count);
framenumber--;
}
printf("\n写入帧数:%u   %ux%u(%d bit)\n", count, frameWidth, frameHeight, bitcount);
sum += count;
printf("\n");
printf("\n");
}
}
}
printf("%d帧YUV写入成功!\n",sum);

/* cleanup */
fclose(bmp);
fclose(yuv);
//free the memory
if (yBuf)   { free(yBuf); }
if (uBuf)   { free(uBuf); }
if (vBuf)   { free(vBuf); }
if (rgbBuf) { free(rgbBuf); }
if (bmpBuf) { free(bmpBuf); }
if (pRGB)   { free(pRGB); }
if (mask16) { free(mask16); }
if (mask32)  { free(mask32); }
return 0;
}


3.BMP2RGB.c

#include "stdlib.h"
#include "bmp2yuv.h"
#include <windows.h>
#include <math.h>

int BMP2RGB32bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *mask)
{
long i;
unsigned char *bmp, *rgb;
Mas32 *mas;
long size = x_dim*y_dim;
bmp = (unsigned char *)bmpbuf;
rgb = (unsigned char *)rgbbuf;
mas = (Mas32 *)mask;

if (mask == NULL)
{
for (i = 0; i < size; i++)
{
*(rgb + 0) = *(bmp + 0);
*(rgb + 1) = *(bmp + 1);
*(rgb + 2) = *(bmp + 2);
rgb += 3;
bmp += 4;
}
return 0;
}
else
{//根据掩码确定RGB比特位
int Gkey, Bkey, Rkey;
if (mas->rgbGreen == 0)
Gkey= 0;
else if (mas->rgbGreen == 0xFF000000)
Gkey = 3;
else if (mas->rgbGreen == 0xFF0000)
Gkey = 2;
else if (mas->rgbGreen == 0xFF00)
Gkey = 1;
else
return 1;

if (mas->rgbBlue == 0)
Bkey = 0;
else if (mas->rgbBlue == 0xFF000000)
Bkey = 3;
else if (mas->rgbBlue == 0xFF0000)
Bkey = 2;
else if (mas->rgbBlue == 0xFF00)
Bkey = 1;
else
return 1;

if (mas->rgbRed == 0)
Rkey = 0;
else if (mas->rgbRed == 0xFF000000)
Rkey = 3;
else if (mas->rgbRed == 0xFF0000)
Rkey = 2;
else if (mas->rgbRed == 0xFF00)
Rkey = 1;
else
return 1;

for (i = 0; i < size; i++)
{
*(rgb + 0) = *(bmp + Bkey);
*(rgb + 1) = *(bmp + Gkey);
*(rgb + 2) = *(bmp + Rkey);
rgb += 3;
bmp += 4;
}
return 0;
}

}

int BMP2RGB24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf)
{
long i;
unsigned char *rgb;// , *raw;
unsigned char *bmp;
long size = x_dim*y_dim;
rgb = (unsigned char *)rgbbuf;
bmp = (unsigned char *)bmpbuf;
for (i = 0; i < size*3; i++)
{
*(rgb + i) = *(bmp + i);
}
return 0;
}
int BMP2RGB16bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *mask)
{
long loop;
unsigned char *Data, *rgbDataOut;
long size = x_dim*y_dim*bitcount / 8;
Data = (unsigned char*)bmpbuf;
rgbDataOut = (unsigned char*)rgbbuf;
Mas16 *mas;
mas = (Mas16 *)mask;

if (mask == NULL)
{
for (loop = 0; loop < size; loop += 2)
{
*rgbDataOut = (*(Data + loop) & 0x1F) << 3;
*(rgbDataOut + 1) = ((*(Data + loop) & 0xE0) >> 2) + ((*(Data + loop + 1) & 0x03) << 6);
*(rgbDataOut + 2) = (*(Data + loop + 1) & 0x7C) << 1;
rgbDataOut += 3;
}
}
else//555 OR 565决定于rgbGreen的比特位
{
if (mas->rgbGreen == 0x07E0)
{
for (loop = 0; loop < size; loop += 2)
{
*rgbDataOut = (*(Data + loop) & 0x1F) << 3;
*(rgbDataOut + 1) = ((*(Data + loop) & 0xE0) >> 3) + ((*(Data + loop + 1) & 0x07) << 5);
*(rgbDataOut + 2) = (*(Data + loop + 1) & 0xF8);
rgbDataOut += 3;
}
}
else
{
for (loop = 0; loop < size; loop += 2)
{
*rgbDataOut = (*(Data + loop) & 0x1F) << 3;
*(rgbDataOut + 1) = ((*(Data + loop) & 0xE0) >> 2) + ((*(Data + loop + 1) & 0x03) << 6);
*(rgbDataOut + 2) = (*(Data + loop + 1) & 0x7C) << 1;
rgbDataOut += 3;
}
}
}
return 0;
}
int BMP2RGBNOT24bit(int bitcount, int x_dim, int y_dim, void *bmpbuf, void *rgbbuf, void *ppRGB)//1\4\8 bit BMP
{
unsigned char *rgb;
unsigned char *bmp;
unsigned char index;

bmp = (unsigned char *)bmpbuf;
rgb = (unsigned char *)rgbbuf;

int shiftCnt;
unsigned char mask;

long loop = 0;
unsigned char *Data, *rgbDataOut;
RGBQUAD* p;

long size = x_dim*y_dim*bitcount/8;
Data = (unsigned char*)bmpbuf;
rgbDataOut = (unsigned char*)rgbbuf;
p = (RGBQUAD*)ppRGB;
for (loop = 0; loop<size; loop++)
{
shiftCnt = 1;
mask = (unsigned char)pow(2, (double)bitcount) - 1;
mask = mask << (8-bitcount);
while (mask)
{
//索引号的确定
index = (mask == 0xFF) ? *(Data + loop) : (*(Data + loop) & mask) >> (8 - shiftCnt * bitcount);
*rgbDataOut = (p + index)->rgbBlue;
*(rgbDataOut + 1) = (p + index)->rgbGreen;
*(rgbDataOut + 2) = (p + index)->rgbRed;
if (bitcount == 8)
mask = 0;
else
mask >>= bitcount;
rgbDataOut += 3;
shiftCnt++;
}
}
return 0;
}


4.RGB2YUV.c

#include "stdlib.h"
#include "bmp2yuv.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;
}

// 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_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;

// convert RGB to YUV
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;
adjust(b, g, r, y, u, v);
b += 3;
y ++;
u ++;
v ++;
}
}
} else {
for (i = 0; i < size; i++)
{
g = b + 1;
r = b + 2;
adjust(b, g, r, y, u,v);
b += 3;
y ++;
u ++;
v ++;
}
}
// subsample UV
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;
}

void adjust(unsigned char *b, unsigned char *g, unsigned char *r, unsigned char *y, unsigned char *u, unsigned char  *v)
{
float temp = 0;
temp = (float)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);
temp = temp>235 ? 235 : temp;
temp = temp<16 ? 16 : temp;
*y = (unsigned char)temp;

temp = (float)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);
temp = temp>240 ? 240 : temp;
temp = temp<16 ? 16 : temp;
*u = (unsigned char)temp;

temp = (float)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);
temp = temp>240 ? 240 : temp;
temp = temp<16 ? 16 : temp;
*v = (unsigned char)temp;
}


四、实验结果

由命令行设置每幅图片播放帧数:4幅图片,每幅转成50帧yuv序列



执行结果如图所示:



不同比特位的bmp位图的对比:

biBitCount原BMP图像生成YUV序列中的一帧
24bit

8bit

4bit

1bit

五、实验总结

本次实验中应重点掌握的是文件格式的概念、字节序、缓冲区分配、结构体操作、倒序读写文件、函数定义等操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: