linux C实现BMP文件转YUV文件
BMP和YUV介绍
(1)BMP介绍
BMP(Bitmap-File) 位图图像, 亦称为点阵图像,区别于矢量图放大不失真的特征,位图图像是由单个像素点组成,放大后会失真。它是 Windows操作系统中的标准系统中的标准图像,是Windows环境中交换与图有关的数据的一种标准。BMP文件属于自包含文件,包含表格中四个部分。BMP 文件的图像深度可选 lbit、4bit、8bit、16bit及24bit 。
位图文件可看成由4个部分组成:位图文件头(bitmap-file header)、位图信息头(bitmap-information header)、彩色表(color table)和定义位图的字节(位图数据,即图像数据,Data Bits 或Data Body)阵列,它具有如下所示的形式
(2)YUV格式
YUV分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
与我们熟知的RGB类似,YUV也是一种颜色编码方法,主要用于电视系统以及模拟视频领域,它将亮度信息(Y)与色彩信息(U/V)分离,没有U/V信息一样可以显示完整的图像,只不过是黑白的,这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。并且,YUV不像RGB那样要求三个独立的视频信号同时传输,所以用YUV方式传送占用极少的频宽。
YUV码流的存储格式其实与其采样的方式密切相关,主流的采样方式有三种,Y:U:V=4:4:4 Y:U:V=4:2:2,Y:U:V=4:2:0。
BMP转YUV公式
Y = 0.299R + 0.587G + 0.114B;
U = -0.169R - 0.331*G + 0.5 B + 128;
V = 0.5 R - 0.419G - 0.081B + 128;
代码实现(注意看注释)
头文件 bmp.h(包含了bmp各个结构体参数 )
值得注意的是:定义结构体的时候 一定要加__attribute__((packed)) (或者 后面字节判定)————取消系统的自动优化对齐 必须要按照自身占用字节对齐
#ifndef _BMP_H_
#define _BMP_H_
/*BMP格式
这种格式内的数据分为三到四个部分,依次是:
文件信息头 (14字节)存储着文件类型,文件大小等信息
图片信息头 (40字节)存储着图像的尺寸,颜色索引,位平面数等信息
调色板 (由颜色索引数决定)【可以没有此信息】
位图数据 (由图像尺寸决定)每一个像素的信息在这里存储
一般的bmp图像都是24位,也就是真彩。每8位为一字节,24位也就是使用三字节来存储每一个像素的信息,三个字节对应存放r,g,b三原色的数据,
每个字节的存贮范围都是0-255。那么以此类推,32位图即每像素存储r,g,b,a(Alpha通道,存储透明度)四种数据。8位图就是只有灰度这一种信息,
还有二值图,它只有两种颜色,黑或者白。
*/
// 文件信息头结构体
typedef struct tagBITMAPFILEHEADER
{
unsigned short bfType; // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件
unsigned int bfSize; // 文件大小 以字节为单位(2-5字节)
unsigned short bfReserved1; // 保留,必须设置为0 (6-7字节)
unsigned short bfReserved2; // 保留,必须设置为0 (8-9字节)
unsigned int bfOffBits; // 从文件头到像素数据的偏移 (10-13字节)
} __attribute__((packed)) BITMAPFILEHEADER; //取消优化对其 按实际占用字节对齐
//图像信息头结构体
typedef struct tagBITMAPINFOHEADER
{
unsigned int biSize; // 此结构体的大小 (14-17字节)
unsigned int biWidth; // 图像的宽 (18-21字节)
unsigned int biHeight; // 图像的高 (22-25字节)
unsigned short biPlanes; // 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1 (26-27字节)
unsigned short biBitCount; // 一像素所占的位数,一般为24 (28-29字节)
unsigned int biCompression; // 说明图象数据压缩的类型,0为不压缩。 (30-33字节)
unsigned int biSizeImage; // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits (34-37字节)
unsigned int biXPelsPerMeter; // 说明水平分辨率,用象素/米表示。一般为0 (38-41字节)
unsigned int biYPelsPerMeter; // 说明垂直分辨率,用象素/米表示。一般为0 (42-45字节)
unsigned int biClrUsed; // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。 (46-49字节)
unsigned int biClrImportant; // 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。(50-53字节)
} __attribute__((packed)) BITMAPINFOHEADER;
//24位图像素信息结构体,即调色板
typedef struct _PixelInfo {
unsigned char rgbBlue; //该颜色的蓝色分量 (值范围为0-255)
unsigned char rgbGreen; //该颜色的绿色分量 (值范围为0-255)
unsigned char rgbRed; //该颜色的红色分量 (值范围为0-255)
unsigned char rgbReserved;// 保留,必须为0
}__attribute__((packed))PixelInfo;
void showBmpHead(BITMAPFILEHEADER fileHeader);
void showBmpInfoHead(BITMAPINFOHEADER infoHeader);
void ReadRGB(FILE *pFile,BITMAPFILEHEADER file_h, BITMAPINFOHEADER info_h, unsigned char*rgbDataOut);
void RGB2YUV(unsigned long w,unsigned long h,unsigned char* rgbData, unsigned char*y,unsigned char*u,unsigned char*v);
int WriteYUV(unsigned char*Y,unsigned char*U,unsigned char*V,unsigned long size,FILE *outFile);
int RGB2YUV2(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);
bool MakePalette(FILE* pFile,BITMAPFILEHEADER file_h, BITMAPINFOHEADER info_h, PixelInfo *pRGB_out);
#endif
模块1 MakePalette :bmp文件开头的调色板数据
//参数: bmp文件,该文件的位图文件头,该文件的位图信息头,输出buffer(bmp文件开头的调色板数据)
bool MakePalette(FILE* pFile,BITMAPFILEHEADER file_h, BITMAPINFOHEADER info_h, PixelInfo *pRGB_out)
{
//先判断是否存在调色板:有效数据开始处离文件开头的距离-位图文件头大小-位图信息头大小=调色数据大小
if ((file_h.bfOffBits- sizeof(BITMAPFILEHEADER)-info_h.biSize)== sizeof(PixelInfo)*pow((float)2,info_h.biBitCount))
{
fseek(pFile,sizeof(BITMAPFILEHEADER)+info_h.biSize,0);
//把调色数据放到pRGB_out中,完成make palette工作
if(fread(pRGB_out, sizeof(PixelInfo), (unsigned long long)pow((float)2,info_h.biBitCount),pFile)!= (unsigned long long)pow((float)2,info_h.biBitCount))
{
printf("Fail to read RGBQUAD!\n");
}
return true;
}
else
return false;
}
ReadRGB:读取bmp文件得到RGB数据
void ReadRGB(FILE *pFile,BITMAPFILEHEADER file_h, BITMAPINFOHEADER info_h, unsigned char*rgbDataOut)
{
unsigned long Loop, iLoop, jLoop, width, height, w, h;
unsigned char mask=0, *Index_Data =NULL , *Data = NULL ;
//保证是图像大小是4字节的整数倍,具体理由见下面的注释
if ((info_h.biWidth% 4) == 0)
w = info_h.biWidth;
else
w = (info_h.biWidth*info_h.biBitCount+ 31) / 32 * 4;
if ((info_h.biHeight% 2) == 0)
h = info_h.biHeight;
else
h = info_h.biHeight+ 1;
//若是24位,则bmp中有效数据大小是长*宽*3字节
//若是16位,则bmp中有效数据大小是长*宽*2字节
//若是8位,则bmp中有效数据大小是长*宽字节
//若是4位,则bmp中有效数据大小是长*宽/2字节
//若是2位,则bmp中有效数据大小是长*宽/4字节
//若是1位,则bmp中有效数据大小是长*宽/8字节(这大概是为什么bmp图像的长必须是4的倍数,宽必须是2的倍数的原因吧。。。)
width = w / 8 * info_h.biBitCount;
height = h;
//倒序前数据缓存区
Index_Data = (unsigned char*)malloc(width*height);//buffer大小应该与bmp中有效数据大小相同
//倒序后数据缓存区,用于存放bmp中的有效数
Data = (unsigned char*)malloc(width*height);//buffer大小应该与bmp中有效数据大小相同
//文件指针定位到有效数据起始处,读取有效数据
fseek(pFile,file_h.bfOffBits,0);
if(fread(Index_Data, 1,height*width, pFile)==0)
{
//printf("%d!\n",fread(Index_Data, height*width, 1, pFile));
printf("read file error !\n");
exit(0);
}
printf("Index_Data[0]:%x!\n",Index_Data[0]);
printf("Index_Data[1]:%x!\n",Index_Data[1]);
printf("Index_Data[1]:%x!\n",Index_Data[2]);
//倒序存放
for (iLoop= 0; iLoop < height; iLoop++)
for (jLoop= 0; jLoop < width; jLoop++)
{
Data[iLoop*width + jLoop] =Index_Data[(height - iLoop - 1)*width + jLoop];
//Data[iLoop*width + jLoop] =Index_Data[iLoop*width + jLoop];
}
//memcpy(Data,Index_Data, height*width);
//24位:直接把倒序后的缓存区数据复制给输出缓存区
int i=0;
if (info_h.biBitCount== 24)
{
// memcpy(rgbDataOut,Data, height*width);
for (i = 0; i < height*width ; i++)
{
*(rgbDataOut + i) = *(Data + i);
}
//printf("rgbBuffer[0]: %x!\n",rgbDataOut[0]);
//printf("rgbBuffer[1]: %x!\n",rgbDataOut[1]);
//printf("rgbBuffer[2]: %x!\n",rgbDataOut[2]);
free(Index_Data);
free(Data);
return;
}
//非24位:解码生成rgb,需要调色板信息
//生成调色板数组,数组的下标,对应bmp文件中有效数据,通过下标对应查找,便可得到该数据对应的颜色
//debug by LiuDong:(unsignedlong long)pow(),pow前的强制类型转换不能转换成unsignedint、unsignedchar等
//因为pow((float)2, info_h.biBitCount)最大值是2^24,unsigned char最大能表示255,unsigned int最大能表示2^32
PixelInfo*pRGB = (PixelInfo *)malloc(sizeof(PixelInfo)*(unsigned long long)pow((float)2,(float)info_h.biBitCount));
/*一个单元代表一种颜色
调色板实际上是一个数组,它所包含的元素与位图所具有的颜色数相同,决定于biClrUsed和biBitCount字段。
数组中每个元素的类型是一个RGBQUAD结构。真彩色无调色板部分。
biBitCount;位数/像素,1、2、4、8、24.假如是16位,R占5位,G占5位,B占5位,空出一位,排列组合一共有2^15种颜色,其他位数同理。*/
//读取位图调色板数据
if(!MakePalette(pFile, file_h,info_h,pRGB))
printf("Nopalette!");
//16位:移位操作,从2字节中取出RGB信息,存到3字节中
if (info_h.biBitCount== 16)
{
for(Loop = 0; Loop < height * width; Loop += 2)
{
*rgbDataOut= (Data[Loop] & 0x1F) << 3;//B:用0001 1111取出低字节的右五位,再放到目标字节的高5位(通过右移3位),得到五位的B
*(rgbDataOut+ 1) = ((Data[Loop] & 0xE0) >> 2) + ((Data[Loop + 1] & 0x03)<< 6);//G:11100000取出低字节的左三位,00000011取出高字节的右两位,合并后,放到再放到目标字节的高5位,得到五位的G
*(rgbDataOut+ 2) = (Data[Loop + 1] & 0x7C) << 1; //R:0111 1100取出高字节的中间五位,再放到目标字节的高5位,得到5位的R
rgbDataOut+= 3;
}//RGB都各自位于字节的高5位
}
//1~8位:移位操作,从有限固定位中取出RGB信息,存到3字节中
//循环次数:有效数据字节数
for (Loop =0; Loop<width*height; Loop++)
{
//根据位深设置掩膜
switch(info_h.biBitCount)
{
case1://1000 0000,1位,黑白双色图
mask = 0x80;
break;
case2://1100 0000,2位,4色图
mask = 0xC0;
break;
case4://1111 0000,4位,16色图
mask = 0xF0;
break;
case8://1000 0000,8位,256色图
mask = 0xFF;
}
int shiftCnt = 1;//控制mask的移位,决定取字节中哪些数据
while(mask)//循环一次就是一个字节的解析过程
{
unsigned char index = mask == 0xFF ? Data[Loop] : ((Data[Loop] & mask) >> (8 - shiftCnt * info_h.biBitCount));
//Loop代表第几个带转换的原始有效数据
//pRGB代表调色板
//8位:mask=1111 1111,index=data[Loop],即index为bmp中原始有效数据,直接对应调色板数组下标,得到相应颜色
//查找调色板,取出对应BGR存入目标buffer:rgbDataOut
*rgbDataOut= pRGB[index].rgbBlue;//B
*(rgbDataOut+ 1) = pRGB[index].rgbGreen;//G
*(rgbDataOut+ 2) = pRGB[index].rgbRed;//R
if(info_h.biBitCount== 8)
mask = 0;//如果是8位bmp,一次性取完一个字节的颜色数据,直接跳出循环即可
else
mask >>= info_h.biBitCount;//若是1位bmp,则一字节取8次数据;若是2位bmp,则一字节取4次数据;若是4位bmp,则一字节取2次数据
//debugby LiuDong
if(Loop == width*height - 1)
{
rgbDataOut= rgbDataOut + 3 - width*height*3;
break;
}
rgbDataOut+= 3;
shiftCnt++;
}
}
if(Index_Data)
free(Index_Data);
if (Data)
free(Data);
if (pRGB)
free(pRGB);
}
RGB2YUV:RGB数据转化为YUV数据
void RGB2YUV(unsigned long w,unsigned long h,unsigned char* rgbData, unsigned char*y,unsigned char*u,unsigned char*v)
{
initLookupTable();//初始化查找表
unsigned char*ytemp = NULL;
unsigned char*utemp = NULL;
unsigned char*vtemp = NULL;
utemp = (unsigned char*)malloc(w*h);
vtemp = (unsigned char*)malloc(w*h);
unsigned long i, nr, ng, nb, nSize,j;
//对每个像素进行 rgb -> yuv的转换
for (i = 0,nSize = 0; nSize<w*h* 3; nSize += 3)
{
nb = rgbData[nSize];
ng = rgbData[nSize+ 1];
nr = rgbData[nSize+ 2];
/*
y[i]= (unsigned char)( (float)0.2990*nr+ (float)0.5870*ng + (float)0.1140*nb);
utemp[i] = (unsigned char)(-(float)0.1684*nr-(float)0.3316*ng + (float)nb / 2 + 128);
vtemp[i] = (unsigned char)((float)nr/2 -(float)0.4187*ng -(float)0.0813*nb + 128);
*/
y[i]= (unsigned char)(RGBYUV02990[nr]+ RGBYUV05870[ng] + RGBYUV01140[nb]);
utemp[i] = (unsigned char)(-RGBYUV01684[nr]- RGBYUV03316[ng] + nb / 2 + 128);
vtemp[i] = (unsigned char)(nr/ 2 - RGBYUV04187[ng] - RGBYUV00813[nb] + 128);
i++;
}
//对u信号及v信号进行采样,因为是4:2:0格式,所以u的数据是y的数据的1/4,v的数据是y的数据的1/4
int k = 0;
for (i = 0;i<h; i += 2)
{
for (j = 0; j<w; j += 2)
{
u[k]= (utemp[i*w + j] + utemp[(i + 1)*w+ j] + utemp[i*w + j + 1] + utemp[(i + 1)*w+ j + 1]) / 4;
v[k]= (vtemp[i*w + j] + vtemp[(i + 1)*w+ j] + vtemp[i*w + j + 1] + vtemp[(i + 1)*w+ j + 1]) / 4;
k++;
}
}
//对y、u、v 信号进行限电平处理
for (i = 0;i<w*h;i++)
{
if(y[i]<16)
y[i]= 16;
if(y[i]>235)
y[i]= 235;
}
for (i = 0;i<h*w/ 4; i++)
{
if(u[i]<16)
u[i]= 16;
if(v[i]<16)
v[i]= 16;
if(u[i]>240)
u[i]= 240;
if(v[i]>240)
v[i]= 240;
}
if (utemp)
free(utemp);
if(vtemp)
free(vtemp);
}
WriteYUV:将YUV文件写入磁盘中
int WriteYUV(unsigned char*Y,unsigned char*U,unsigned char*V,unsigned long size,FILE *outFile)
{
if(fwrite(Y, 1, size,outFile)!= size)
return -1;
if(fwrite(U, 1, size/ 4, outFile) != size/ 4)
return -1;
if(fwrite(V, 1, size/ 4, outFile) != size/ 4)
return -1;
return 0;
}
initLookupTable:YUV转换需要的参数
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;
}
主函数main.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <linux/fb.h>
#include <math.h>
#include <stdbool.h>
#include "bmp.h"
int main()
{
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
FILE* bmpFile;
FILE* yuvFile;
unsigned char*rgbBuffer, *yBuffer, *uBuffer, *vBuffer;
bmpFile = fopen("3.bmp", "rb");//读取同目录下的image.bmp文件。
yuvFile=fopen("3.yuv" , "wb+");
if( bmpFile == NULL)
{
printf("打开'image.bmp'失败!\n");
return -1;
}
if(fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, bmpFile) != 1)
{
printf("read file header error!\n");
return -1;
}
//判断文件类型
if(fileHeader.bfType != 0x4D42)
{
printf("Not bmp file!\n");
return -1;
}
else
{
printf("this is a bmp file\n");
}
//读取位图信息头
if(fread(&infoHeader,sizeof(BITMAPINFOHEADER), 1,bmpFile) == 0)
{
printf("read info header error!\n");
return -1;
}
unsigned long width, height;
if(infoHeader.biWidth % 4 == 0)
width = infoHeader.biWidth;
else
width =(infoHeader.biWidth*infoHeader.biBitCount + 31) / 32 * (32 / 8);
if((infoHeader.biHeight % 2) == 0)
height = infoHeader.biHeight;
else
height = infoHeader.biHeight + 1;
rgbBuffer = (unsigned char*)malloc(height*width* 3);
yBuffer = (unsigned char*)malloc(height*width);
uBuffer = (unsigned char*)malloc(height*width/4);
vBuffer = (unsigned char*)malloc(height*width/4);
printf("width: %ld!\n",width);
printf("height: %ld!\n",height);
ReadRGB(bmpFile, fileHeader,infoHeader, rgbBuffer);
//return 0;
showBmpHead(fileHeader);
showBmpInfoHead(infoHeader);
//return 0;
///*
printf("rgbBuffer[0]: %x!\n",rgbBuffer[0]);
printf("rgbBuffer[1]: %x!\n",rgbBuffer[1]);
printf("rgbBuffer[2]: %x!\n",rgbBuffer[2]);
//RGB2YUV(width, height, rgbBuffer,yBuffer, uBuffer, vBuffer);
//printf("rgbBuffer[0]: %x!\n",rgbBuffer[0]);
//printf("rgbBuffer[1]: %x!\n",rgbBuffer[1]);
//printf("rgbBuffer[2]: %x!\n",rgbBuffer[2]);
//*/
RGB2YUV2(width, height, rgbBuffer, yBuffer, uBuffer, vBuffer, 0);
//char yuvFile[100]="WJN.yuv";
if (yuvFile == NULL)
{
printf("Fail\n");
exit(0);
}
else
{
printf("output file is %s\n", "2.yuv");
printf("\n");
}
if((WriteYUV(yBuffer, uBuffer, vBuffer, width*height, yuvFile))==0)
printf("writeYUV file successful!\n");
else
printf("writeYUV file failed!\n");
if(rgbBuffer)
free(rgbBuffer);
if(yBuffer)
free(yBuffer);
if(uBuffer)
free(uBuffer);
if(vBuffer)
free(vBuffer);
fclose(bmpFile);
fclose(yuvFile);
return 0;
}
知道大家时间都宝贵 bmp.c文件我也直接给出吧!!!
#ifndef _BMP_H_
#define _BMP_H_
/*BMP格式
这种格式内的数据分为三到四个部分,依次是:
文件信息头 (14字节)存储着文件类型,文件大小等信息
图片信息头 (40字节)存储着图像的尺寸,颜色索引,位平面数等信息
调色板 (由颜色索引数决定)【可以没有此信息】
位图数据 (由图像尺寸决定)每一个像素的信息在这里存储
一般的bmp图像都是24位,也就是真彩。每8位为一字节,24位也就是使用三字节来存储每一个像素的信息,三个字节对应存放r,g,b三原色的数据,
每个字节的存贮范围都是0-255。那么以此类推,32位图即每像素存储r,g,b,a(Alpha通道,存储透明度)四种数据。8位图就是只有灰度这一种信息,
还有二值图,它只有两种颜色,黑或者白。
*/
// 文件信息头结构体
typedef struct tagBITMAPFILEHEADER
{
unsigned short bfType; // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件
unsigned int bfSize; // 文件大小 以字节为单位(2-5字节)
unsigned short bfReserved1; // 保留,必须设置为0 (6-7字节)
unsigned short bfReserved2; // 保留,必须设置为0 (8-9字节)
unsigned int bfOffBits; // 从文件头到像素数据的偏移 (10-13字节)
} __attribute__((packed)) BITMAPFILEHEADER; //取消优化对齐 按实际占用字节对齐
//图像信息头结构体
typedef struct tagBITMAPINFOHEADER
{
unsigned int biSize; // 此结构体的大小 (14-17字节)
unsigned int biWidth; // 图像的宽 (18-21字节)
unsigned int biHeight; // 图像的高 (22-25字节)
unsigned short biPlanes; // 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1 (26-27字节)
unsigned short biBitCount; // 一像素所占的位数,一般为24 (28-29字节)
unsigned int biCompression; // 说明图象数据压缩的类型,0为不压缩。 (30-33字节)
unsigned int biSizeImage; // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits (34-37字节)
unsigned int biXPelsPerMeter; // 说明水平分辨率,用象素/米表示。一般为0 (38-41字节)
unsigned int biYPelsPerMeter; // 说明垂直分辨率,用象素/米表示。一般为0 (42-45字节)
unsigned int biClrUsed; // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。 (46-49字节)
unsigned int biClrImportant; // 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。(50-53字节)
} __attribute__((packed)) BITMAPINFOHEADER;
//24位图像素信息结构体,即调色板
typedef struct _PixelInfo {
unsigned char rgbBlue; //该颜色的蓝色分量 (值范围为0-255)
unsigned char rgbGreen; //该颜色的绿色分量 (值范围为0-255)
unsigned char rgbRed; //该颜色的红色分量 (值范围为0-255)
unsigned char rgbReserved;// 保留,必须为0
}__attribute__((packed))PixelInfo;
void showBmpHead(BITMAPFILEHEADER fileHeader);
void showBmpInfoHead(BITMAPINFOHEADER infoHeader);
void ReadRGB(FILE *pFile,BITMAPFILEHEADER file_h, BITMAPINFOHEADER info_h, unsigned char*rgbDataOut);
void RGB2YUV(unsigned long w,unsigned long h,unsigned char* rgbData, unsigned char*y,unsigned char*u,unsigned char*v);
int WriteYUV(unsigned char*Y,unsigned char*U,unsigned char*V,unsigned long size,FILE *outFile);
int RGB2YUV2(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);
bool MakePalette(FILE* pFile,BITMAPFILEHEADER file_h, BITMAPINFOHEADER info_h, PixelInfo *pRGB_out);
#endif
想要工程文件的也可以下载!!!
代码下载地址:https://blog.csdn.net/qq_31387349?spm=1011.2124.3001.5343&type=download