windows程序设计之DIB操作

主要介绍下与设备无关的位图DIB(Device Independent Bitmap)


位图的基本格式
1.文件头
typedef struct tagBITMAPFILEHEADER {
        WORD    bfType;//bmp图类型为'BM'或者0X4D42
        DWORD   bfSize;//整个文件大小
        WORD    bfReserved1;//0
        WORD    bfReserved2;//0
        DWORD   bfOffBits;//DIB像素数据偏移
} BITMAPFILEHEADER
2.信息头
typedef struct tagBITMAPINFOHEADER{
        DWORD      biSize;//结构体大小 = 40
        LONG       biWidth;//文件宽度(像素)
        LONG       biHeight;//文件高度(像素)
        WORD       biPlanes;//1
        WORD       biBitCount;//每像素位数(1,4,8,16,24,32)
        DWORD      biCompression;//压缩方式
        DWORD      biSizeImage;//实际位图数据占用的字节数
        LONG       biXPelsPerMeter;//X方向分辨率
        LONG       biYPelsPerMeter;//Y方向分辨率
        DWORD      biClrUsed;//使用的颜色数
        DWORD      biClrImportant;//重要颜色数

} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

biBitCount字段
$ 1(2色DIB)
$ 4(16色DIB)
$ 8(256色DIB)
$ 24(全色DIB)
 
3.RGB色彩表(不一定有)
对于像素位(biBitCount字段)是1,4,和8时,BITMAPINFOHEADER后面跟着的是色彩表。
typedef struct tagRGBQUAD {
        BYTE    rgbBlue;//蓝色
        BYTE    rgbGreen;//绿色
        BYTE    rgbRed;//红色
        BYTE    rgbReserved;//保留,0
} RGBQUAD;

每个像素点都是一个RGB,三种色彩组成颜色。要注意的就是里面的元素顺序是BGR。


4.位图像素位
这里才是图像数据的真实存放处,可以在这里读取图像的数据进行操作。每个像素点都是由RGB数组构成。要注意的是,在DIB中,图像的底行是文件的第一行,图像的顶行是文件的最后一行。但是对于同一行来说,还是从左到右存放数据的。windows程序设计上是这样说的:从下到上DIB的原点是位图图像的左下角,它是图像的第一行的第一个像素。从上到下DIB的原点也是位图图像的左下角,但是这种情况下,左下角是位图数据的最后一行的第一个像素。
DIB中的行数是BITMAPINFOHEADER结构中的biHeight字段,每一行的像素是该结构中biWidth字段,每一行从左边开始,向右数,每个像素位数由bcBitCount确定。
每行的长度必须是4的倍数。
RowLength = 4 * ((bmch.bcWidth * bmch.bcBitCount + 31) / 32)计算;

总的像素位数据大小 = RowLength *bmch.biHeight计算。

下面是对DIB文件的读写:

/****************************************************************************
*函数名称: ReadBmp()
*函数参数: const char *bmpName    写入bmp格式文件的名称及路径
***************************************************************************/
bool ReadBmp(const char *strFile)
{
	BITMAPFILEHEADER   bitHead;   
	BITMAPINFOHEADER bitInfoHead;    
	FILE* pfile;    

	pfile = fopen(strFile,"rb");//打开文件   

	if(pfile!=NULL)   
	{   
		printf("file bkwood.bmp open success.\n");   
		//读取位图文件头信息   
		fread(&bitHead,1,sizeof(BITMAPFILEHEADER),pfile);   
		//fseek(pfile,2,SEEK_CUR);   // "BM"
		if(bitHead.bfType != 0x4d42)   
		{   
			printf("file is not .bmp file!");   
			return false;   
		}  
		//读取位图信息头信息   
		fread(&bitInfoHead,1,sizeof(BITMAPINFOHEADER),pfile);   
	}
	tagRGBQUAD *pRgb ;   
	int width = bitInfoHead.biWidth;   
	int height = bitInfoHead.biHeight;   
	//分配内存空间把源图存入内存      
	int l_width   =  4 * ((width* bitInfoHead.biBitCount+31) /32);//计算位图的实际宽度并确保它为32的倍数   
	BYTE    *pColorData=(BYTE *)malloc(height*l_width);      
	memset(pColorData,0,height*l_width);      
	long nData = height*l_width;   

	//把位图数据信息读到数组里      
	fread(pColorData,1,nData,pfile);  
	fclose(pfile);
	return true;
}


/****************************************************************************
*函数名称: saveBmp()

unsigned char *imgBuf 待存盘的位图数据
int width,             以像素为单位待存盘的位图宽
int height,            以像素为单位待存盘的位图高
int biBitCount,        每个像素占的位数
RGBQUAD *pColorTable   颜色表指针
*函数返回值:0为失败 1为成功
*函数描述:给定写入bmp文件的名称和路径 要写入图像的位图数据,宽,高,写进文件中
*
***************************************************************************/
bool saveBmp(const char* bmpName,unsigned char *imgBuf,int width,int height,int biBitCount,RGBQUAD *pColorTable)
{
	if(!imgBuf)//imgBuf 待存盘的位图数据
		return 0;
		
	int colorTablesize = 0;
	if(biBitCount == 8)
		colorTablesize =1024;
		
	int lineByte = (width * biBitCount/8+3)/4*4; 			//行的长度。以字节为单位的每行长度始终是4的倍数
	
	FILE *fp = fopen(bmpName,"wb");
		if(fp == 0) return 0;
		
	BITMAPFILEHEADER fileHead;								//文件头
	fileHead.bfType= 0x4d42;								//确保是bmp图像:"BM"
	fileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER) + colorTablesize + lineByte *height;	//图像大小
	fileHead.bfReserved1 = 0;					
	fileHead.bfReserved2 = 0;
	fileHead.bfOffBits = 54 +colorTablesize;
	
	fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);		//写图像文件头
	
	BITMAPINFOHEADER head;									//信息头
	head.biBitCount = biBitCount;							//每像素的位数
	head.biClrImportant = 0;
	head.biClrUsed = 0;
	head.biCompression = 0;
	head.biHeight = height;									//图像高度
	head.biPlanes =1;
	head.biSize = 40;
	head.biSizeImage = lineByte *height;					//图像字节数
	head.biWidth = width;									//图像高度			
	head.biXPelsPerMeter = 0;
	head.biYPelsPerMeter = 0;
	
	fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp);			//写图像文件信息头
	
	if(biBitCount == 8)										//如果是8bits,写入色彩表
		fwrite(pColorTable,sizeof(RGBQUAD),256,fp);
		
	fwrite(imgBuf,height * lineByte,1,fp);					//写图像的数据内容
	fclose(fp);
	return 1;	
}



你可能感兴趣的:(windows,struct,File,null,byte,FP)