bmp/dib文件的格式

Bmp又叫dib文件

任何一个bmp文件都包含这四个信息

『文件头 / 信息头 / 颜色表 / 像素位』

1.文件头: 

文件头个14个字节的结构体

struct tagBITMAPFILEHEADER

{

       WORD bfType;       

       DWORD bfSize;

       WORD      bfReserved1;

       WORD bfReserved2;

       DWORDbfOffsetBits;

};


bfType 表示文件签名   即”BM”两个字母  也就是16进制的0X4D42

bfSize 表示该图片文件的大小

bfReserved1;    一般不用,值为0

bfReserved2;     一般不用,值为0

bfOffsetBits;    表示从文件头到像素位的偏移,这个比较重要、、

2.信息头:

信息头随着时代的不同,有四种版本的信息头:

1.tagBITMAPCOREHEADER版本

————————————————————

typedef struct tagBITMAPCOREHEADER {

       DWORD   bcSize;          //结构的大小 = 12

       WORD    bcWidth;

       WORD    bcHeight;

       WORD    bcPlanes;

       WORD    bcBitCount;

} BITMAPCOREHEADER;

2.tagBITMAPINFOHEADER版本

 ————————————————————

typedef struct tagBITMAPINFOHEADER{

       DWORD      biSize;    //结构的大小 = 40

       LONG       biWidth;

       LONG       biHeight;

       WORD       biPlanes;

       WORD       biBitCount;

       DWORD      biCompression;

       DWORD      biSizeImage;

       LONG       biXPelsPerMeter;

       LONG       biYPelsPerMeter;

       DWORD      biClrUsed;

       DWORD      biClrImportant;

} BITMAPINFOHEADER;

3.BITMAPV4HEADER版本

————————————————————

typedef struct {

       DWORD        bV4Size;    //结构的大小 = 108

       LONG         bV4Width;

       LONG         bV4Height;

        WORD        bV4Planes;

       WORD         bV4BitCount;

       DWORD        bV4V4Compression;

       DWORD        bV4SizeImage;

       LONG         bV4XPelsPerMeter;

       LONG         bV4YPelsPerMeter;

       DWORD        bV4ClrUsed;

       DWORD        bV4ClrImportant;

        …

       CIEXYZTRIPLE bV4Endpoints;

       DWORD        bV4GammaRed;

       DWORD        bV4GammaGreen;

       DWORD        bV4GammaBlue;

} BITMAPV4HEADER;

4.BITMAPV5HEADER版本 

——————————————————————

 typedef struct {

       DWORD        bV5Size;    //结构的大小 = 124

       LONG         bV5Width;

       LONG         bV5Height;

       WORD         bV5Planes;

       WORD         bV5BitCount;

       DWORD        bV5Compression;

       DWORD        bV5SizeImage;

       LONG         bV5XPelsPerMeter;

       LONG         bV5YPelsPerMeter;

       DWORD        bV5ClrUsed;

       DWORD        bV5ClrImportant;

           …

           …

       DWORD        bV5ProfileData;

       DWORD        bV5ProfileSize;

       DWORD        bV5Reserved;

} BITMAPV5HEADER

——————————————

后面的版本是前面版本的扩充,包括以前版本的字段:

其中有一些字段是比较重要的:(就以tagBITMAPCOREHEADER类型为例,其他只是名字不同

DWORD  bcSize;          //结构的大小,

WORD   bcWidth;                 //图片的宽度

WORD   bcHeight;                //图片的高度

WORD   bcPlanes;                

WORD   bcBitCount;            //颜色为数量


一般读取信息头的时候把变量定义成版本BITMAPV5HEADER,因为我们不能确定所读取的文件信息头是那个版本的信息头,而V5 的信息头结构最大,字段最多,包括了其他版本的信息头的字段,所以我们用最大的去读,然后通过其中bV5Size这个字段得知该信息头的大小,而每种版本的信息头大小恰好不同!!!,这样就确定他是那种信息头

void DisplayDibHeaders(HWND hwnd, TCHAR *szFileName)
{//显示一个位图的信息,其中Printf为一个自定义函数
	static TCHAR *szInfoName[] = {
		TEXT("BITMAPCOREHEADER"),
		TEXT("BITMAPINFOHEADER"),
		TEXT("BITMAPV4HEADER"),
		TEXT("BITMAPV5HEADER")};
	static TCHAR *szCompression[] = {
		TEXT("BI_RGB"),
		TEXT("BI_RLE8"),
		TEXT("BI_RLE4"),
		TEXT("BI_BITFIELDS"),
		TEXT("unknown")
	};
	HANDLE hFile;
	DWORD dwFileSize, dwHighSize, dwBytesRead;
	PBYTE pFile;
	BOOL bSuccess;
	BITMAPFILEHEADER *pbmfh;
	BITMAPV5HEADER *pbmih;
	BITMAPCOREHEADER *pbmch;
	int i;
	TCHAR *szV;
	
	Printf(hwnd, TEXT("File: %s\r\n\r\n"), szFileName);

	//打开文件,读文件
	hFile = CreateFile(szFileName, GENERIC_READ,FILE_SHARE_READ,
		0,OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,NULL);
	if(hFile == INVALID_HANDLE_VALUE)
	{
		Printf(hwnd, TEXT("Cannot open file.\r\n\rn"));
		return;
	}
	dwFileSize = GetFileSize(hFile,&dwHighSize);
	if(dwHighSize)
	{//如果是大文件
		Printf(hwnd, TEXT("Cannot deal with >4G files.\r\n\r\n"));
		CloseHandle(hFile);
		return;
	}

	pFile = (PBYTE)malloc(dwFileSize);
	if(!pFile){
		Printf(hwnd,TEXT("Cannot allocate memory.\r\n\r\n"));
		CloseHandle(hFile);
		return;
	}

	bSuccess = ReadFile(hFile,pFile,dwFileSize,&dwBytesRead,NULL);
	if(!bSuccess)
	{
		Printf(hwnd, TEXT("Could not read file.\r\n\r\n"));
		CloseHandle(hFile);
		free(pFile);
		return;
	}
	CloseHandle(hFile);

	pbmfh = (BITMAPFILEHEADER *)pFile;
<span style="white-space:pre">	</span>//输出文件头信息
	Printf(hwnd, TEXT("BITMAPFILEHEADER\r\n"));
	Printf(hwnd, TEXT("\t.bfType = 0x%X\r\n"), pbmfh->bfType);
	Printf(hwnd, TEXT("\t.bfSize = %u\r\n"), pbmfh->bfSize);
	Printf(hwnd, TEXT("\t.bfReserved1 = %u\r\n"), pbmfh->bfReserved1);
	Printf(hwnd, TEXT("\t.bfReserved2 = %u\r\n"), pbmfh->bfReserved2);
	Printf(hwnd, TEXT("\t.bfOffBits = %u\r\n\r\n"), pbmfh->bfOffBits);
<span style="white-space:pre">	</span>
	pbmih = (BITMAPV5HEADER *)(pFile + sizeof(BITMAPFILEHEADER));<span style="white-space:pre">	</span>//以最大的版本去读

	switch(pbmih->bV5Size)
	{
	case sizeof(BITMAPCOREHEADER): 
		i = 0;
		break;
	case sizeof(BITMAPINFOHEADER):
		i = 1;
		szV = TEXT("i");
		break;
	case sizeof(BITMAPV4HEADER):
		i = 2;
		szV = TEXT("V4");
		break;
	case sizeof(BITMAPV5HEADER):
		i = 3;
		szV = TEXT("V5");
		break;
	default:
		Printf(hwnd, TEXT("Unknown header size of %u.\r\n\r\n"), pbmih->bV5Size);
		free(pFile);
		return;
	}

	Printf(hwnd, TEXT("%s\r\n"), szInfoName[i]);

	if(pbmih->bV5Size == sizeof(BITMAPCOREHEADER))
	{
		pbmch = (BITMAPCOREHEADER *)pbmih;
		Printf(hwnd, TEXT("\t.bcSize = %u\r\n"), pbmch->bcSize);
		Printf(hwnd, TEXT("\t.bcWidth = %u\r\n"), pbmch->bcWidth);
		Printf(hwnd, TEXT("\t.bcHeight = %u\r\n"), pbmch->bcHeight);
		Printf(hwnd, TEXT("\t.bcPlanes = %u\r\n"), pbmch->bcPlanes);
		Printf(hwnd, TEXT("\t.bcBitCount = %u\r\n"), pbmch->bcBitCount);
		free(pFile);
		return;
	}

	Printf (hwnd, TEXT ("\t.b%sSize = %u\r\n"), szV, pbmih->bV5Size);
	Printf (hwnd, TEXT ("\t.b%sWidth = %i\r\n"), szV, pbmih->bV5Width);
	Printf (hwnd, TEXT ("\t.b%sHeight = %i\r\n"), szV, pbmih->bV5Height) ;
	Printf (hwnd, TEXT ("\t.b%sPlanes = %u\r\n"), szV, pbmih->bV5Planes) ;
	Printf (hwnd, TEXT ("\t.b%sBitCount = %u\r\n"), szV, pbmih->bV5BitCount) ;
	Printf (hwnd, TEXT ("\t.b%sCompression = %s\r\n"), szV, szCompression [min (4, pbmih->bV5Compression)]) ;
	Printf (hwnd, TEXT ("\t.b%sSizeImage = %u\r\n"), szV, pbmih->bV5SizeImage);
	Printf (hwnd, TEXT ("\t.b%sXPelsPerMeter = %i\r\n"), szV, pbmih->bV5XPelsPerMeter) ;
	Printf (hwnd, TEXT ("\t.b%sYPelsPerMeter = %i\r\n"), szV, pbmih->bV5YPelsPerMeter) ;
	Printf (hwnd, TEXT ("\t.b%sClrUsed = %i\r\n"), szV, pbmih->bV5ClrUsed) ;
	Printf (hwnd, TEXT ("\t.b%sClrImportant = %i\r\n\r\n"), szV, pbmih->bV5ClrImportant) ;

	if(pbmih->bV5Size == sizeof(BITMAPINFOHEADER))
	{
		if(pbmih->bV5Compression == BI_BITFIELDS)
		{
			Printf(hwnd, TEXT("Red Mask = %08X\r\n"), pbmih->bV5RedMask);
			Printf(hwnd, TEXT("Green Mask = %08X\r\n"), pbmih->bV5GreenMask);
			Printf(hwnd, TEXT("Blue Mask = %08X\r\n\r\n"), pbmih->bV5BlueMask);
		}
		free(pFile);
		return;
	}

	Printf (hwnd, TEXT ("\t.b%sRedMask = %08X\r\n"), szV, pbmih->bV5RedMask);
	Printf (hwnd, TEXT ("\t.b%sGreenMask = %08X\r\n"), szV, pbmih->bV5GreenMask) ;
	Printf (hwnd, TEXT ("\t.b%sBlueMask  = %08X\r\n"), szV, pbmih->bV5BlueMask) ;
	Printf (hwnd, TEXT ("\t.b%sAlphaMask = %08X\r\n"), szV, pbmih->bV5AlphaMask) ;
	Printf (hwnd, TEXT ("\t.b%sCSType = %u\r\n"), szV, pbmih->bV5CSType) ;
	Printf (hwnd, TEXT ("\t.b%sEndpoints.ciexyzRed.ciexyzX   = %08X\r\n"), szV, pbmih->bV5Endpoints.ciexyzRed.ciexyzX) ;
	Printf (hwnd, TEXT ("\t.b%sEndpoints.ciexyzRed.ciexyzY   = %08X\r\n"), szV, pbmih->bV5Endpoints.ciexyzRed.ciexyzY) ;
	Printf (hwnd, TEXT ("\t.b%sEndpoints.ciexyzRed.ciexyzZ   = %08X\r\n"), szV, pbmih->bV5Endpoints.ciexyzRed.ciexyzZ) ;
	Printf (hwnd, TEXT ("\t.b%sEndpoints.ciexyzGreen.ciexyzX = %08X\r\n"), szV, pbmih->bV5Endpoints.ciexyzGreen.ciexyzX) ;
	Printf (hwnd, TEXT ("\t.b%sEndpoints.ciexyzGreen.ciexyzY = %08X\r\n"), szV, pbmih->bV5Endpoints.ciexyzGreen.ciexyzY) ;
	Printf (hwnd, TEXT ("\t.b%sEndpoints.ciexyzGreen.ciexyzZ = %08X\r\n"), szV, pbmih->bV5Endpoints.ciexyzGreen.ciexyzZ) ;
	Printf (hwnd, TEXT ("\t.b%sEndpoints.ciexyzBlue.ciexyzX  = %08X\r\n"), szV, pbmih->bV5Endpoints.ciexyzBlue.ciexyzX) ;
	Printf (hwnd, TEXT ("\t.b%sEndpoints.ciexyzBlue.ciexyzY  = %08X\r\n"), szV, pbmih->bV5Endpoints.ciexyzBlue.ciexyzY) ;
	Printf (hwnd, TEXT ("\t.b%sEndpoints.ciexyzBlue.ciexyzZ  = %08X\r\n"), szV, pbmih->bV5Endpoints.ciexyzBlue.ciexyzZ) ;
	Printf (hwnd, TEXT ("\t.b%sGammaRed   = %08X\r\n"), szV, pbmih->bV5GammaRed) ;
	Printf (hwnd, TEXT ("\t.b%sGammaGreen = %08X\r\n"), szV, pbmih->bV5GammaGreen) ;
	Printf (hwnd, TEXT ("\t.b%sGammaBlue  = %08X\r\n\r\n"), szV, pbmih->bV5GammaBlue) ;

	if(pbmih->bV5Size == sizeof(BITMAPV4HEADER))
	{
		free(pFile);
		return;
	}

	Printf (hwnd, TEXT ("\t.b%sIntent = %u\r\n"), szV, pbmih->bV5Intent);
	Printf (hwnd, TEXT ("\t.b%sProfileData = %u\r\n"), szV, pbmih->bV5ProfileData) ;
	Printf (hwnd, TEXT ("\t.b%sProfileSize = %u\r\n"), szV, pbmih->bV5ProfileSize) ;
	Printf (hwnd, TEXT ("\t.b%sReserved = %u\r\n\r\n"), szV, pbmih->bV5Reserved) ;

	free(pFile);
	return;
}
下面显示了如何显示一个BMP文件

<pre name="code" class="cpp">void DibFileInitialize(HWND hwnd)
{//初始化一个OPENFILE结构
	static TCHAR szFilter[] =  TEXT("BitmapFile(*.bmp)\0*.bmp\0")
		TEXT("All Files(*.*)\0*.*\0\0");

	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hwnd;
	ofn.hInstance = NULL;
	ofn.lpstrFilter = szFilter;
	ofn.lpstrCustomFilter = NULL;
	ofn.nMaxCustFilter = 0;
	ofn.nFilterIndex = 0;
	ofn.lpstrFile = NULL;
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFileTitle = NULL;
	ofn.nMaxFileTitle = MAX_PATH;
	ofn.lpstrInitialDir = NULL;
	ofn.lpstrTitle = NULL;
	ofn.Flags = 0;
	ofn.nFileOffset = 0;
	ofn.nFileExtension = 0;
	ofn.lpstrDefExt = TEXT("bmp");
	ofn.lCustData = 0;
	ofn.lpfnHook = NULL;
	ofn.lpTemplateName = NULL;
}


BOOL DibFileOpenDlg(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
{
	ofn.hwndOwner = hwnd;
	ofn.lpstrFile = pstrFileName;
	ofn.lpstrFileTitle = pstrTitleName;
	ofn.Flags = 0;

	return GetOpenFileName(&ofn);
}


BITMAPFILEHEADER* DibLoadImage(PTSTR pstrFileName)
{
	BOOL bSuccess;
	DWORD dwFileSize, dwHighSize, dwBytesRead;
	HANDLE hFile;
	BITMAPFILEHEADER * pbmfh;

	hFile = CreateFile(pstrFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
		OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);

	if (hFile == INVALID_HANDLE_VALUE)
		return NULL;
	dwFileSize = GetFileSize(hFile, &dwHighSize);
	if (dwHighSize)
	{
		CloseHandle(hFile);
		return NULL;
	}
	pbmfh = (BITMAPFILEHEADER*)malloc(dwFileSize);
	if (!pbmfh)
	{
		CloseHandle(hFile);
		return NULL;
	}
	bSuccess = ReadFile(hFile, pbmfh, dwFileSize, &dwBytesRead, NULL);
	CloseHandle(hFile);
	
	if (!bSuccess || (dwBytesRead != dwFileSize)
		|| (pbmfh->bfType != *(WORD*)"BM")
		|| (pbmfh->bfSize != dwFileSize))
	{
		free(pbmfh);
		return NULL;
	}
	return pbmfh;

}

 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static BITMAPFILEHEADER* pbmfh;
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;
	static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
	static BITMAPINFO* pbmi;
	static BYTE* pBits;
	static int cxDib, cyDib;

	switch (message)
	{
	case WM_CREATE:
		DibFileInitialize(hWnd);
		return 0;
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// 分析菜单选择: 
		switch (wmId)
		{
		case IDM_OPEN:
			if (!DibFileOpenDlg(hWnd, szFileName, szTitleName))
				return 0;

			if (pbmfh)
			{
				free(pbmfh);
				pbmfh = NULL;
			}
			pbmfh = DibLoadImage(szFileName);

			InvalidateRect(hWnd, NULL, TRUE);

			pbmi = (BITMAPINFO*)(pbmfh + 1);
			pBits = (BYTE*)pbmfh + pbmfh->bfOffBits;

			if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREINFO))
			{
				cxDib = ((BITMAPCOREHEADER*)pbmi)->bcWidth;
				cyDib = ((BITMAPCOREHEADER*)pbmi)->bcHeight;
			}
			else
			{
				cxDib = pbmi->bmiHeader.biWidth;
				cyDib = abs(pbmi->bmiHeader.biHeight);
			}

			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO:  在此添加任意绘图代码...
		if (pbmfh)
			SetDIBitsToDevice(hdc, 100, 50, cxDib, cyDib, 0, 0, 0, cyDib, pBits, pbmi, DIB_RGB_COLORS);
		EndPaint(hWnd, &ps);
		break;
	case WM_DESTROY:
		if (pbmfh)
			free(pbmfh);
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值