linux C实现BMP文件转YUV文件

1 篇文章 0 订阅
1 篇文章 0 订阅

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.169
R - 0.331*G + 0.5 B + 128;
  V = 0.5 R - 0.419G - 0.081
B + 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 00001位,黑白双色图
            mask = 0x80;
            break;
        case2://1100 00002位,4色图
            mask = 0xC0;
            break;
        case4://1111 00004位,16色图
            mask = 0xF0;
            break;
        case8://1000 00008位,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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值