www.pudn.com > bmp_info.rar > bmp_info.cpp


// bmp_info.cpp : Defines the entry point for the application. 
// 
 
#include "stdafx.h" 
#include "bmp_info.h" 
#include "bmpinfo.h" 
 
#define MAX_LOADSTRING 100 
 
// Global Variables: 
HINSTANCE hInst;								// current instance 
TCHAR szTitle[MAX_LOADSTRING];					// The title bar text 
TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name 
 
// Forward declarations of functions included in this code module: 
ATOM				MyRegisterClass(HINSTANCE hInstance); 
BOOL				InitInstance(HINSTANCE, int); 
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM); 
INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM); 
 
 
// For (HWND hWnd, char *BmpFileName) Begin: 
#include  
#include  
#include  
 
BITMAPFILEHEADER   bf; 
BITMAPINFOHEADER   bi; 
 
#define WIDTHBYTES(i)  ((i+31)/32*4) 
 
HANDLE hImgData; 
char BmpFileName[256] = "c:\\test.bmp"; 
// For (HWND hWnd, char *BmpFileName) end: 
 
 
BOOL LoadBmpFile (HWND hWnd, char *BmpFileName); 
void Message_Box (HWND hWnd, char content[]); 
 
int APIENTRY _tWinMain(HINSTANCE hInstance, 
                       HINSTANCE hPrevInstance, 
                       LPTSTR    lpCmdLine, 
                       int       nCmdShow) 
{ 
	UNREFERENCED_PARAMETER(hPrevInstance); 
	UNREFERENCED_PARAMETER(lpCmdLine); 
 
 	// TODO: Place code here. 
	MSG msg; 
	HACCEL hAccelTable; 
 
	// Initialize global strings 
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 
	LoadString(hInstance, IDC_BMP_INFO, szWindowClass, MAX_LOADSTRING); 
	MyRegisterClass(hInstance); 
 
	// Perform application initialization: 
	if (!InitInstance (hInstance, nCmdShow)) 
	{ 
		return FALSE; 
	} 
 
	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_BMP_INFO)); 
 
	// Main message loop: 
	while (GetMessage(&msg, NULL, 0, 0)) 
	{ 
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{ 
			TranslateMessage(&msg); 
			DispatchMessage(&msg); 
		} 
	} 
 
	return (int) msg.wParam; 
} 
 
 
// 
//  FUNCTION: MyRegisterClass() 
// 
//  PURPOSE: Registers the window class. 
// 
//  COMMENTS: 
// 
//    This function and its usage are only necessary if you want this code 
//    to be compatible with Win32 systems prior to the 'RegisterClassEx' 
//    function that was added to Windows 95. It is important to call this function 
//    so that the application will get 'well formed' small icons associated 
//    with it. 
// 
ATOM MyRegisterClass(HINSTANCE hInstance) 
{ 
	WNDCLASSEX wcex; 
 
	wcex.cbSize = sizeof(WNDCLASSEX); 
 
	wcex.style			= CS_HREDRAW | CS_VREDRAW; 
	wcex.lpfnWndProc	= WndProc; 
	wcex.cbClsExtra		= 0; 
	wcex.cbWndExtra		= 0; 
	wcex.hInstance		= hInstance; 
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_BMP_INFO)); 
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW); 
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1); 
	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_BMP_INFO); 
	wcex.lpszClassName	= szWindowClass; 
	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 
 
	return RegisterClassEx(&wcex); 
} 
 
// 
//   FUNCTION: InitInstance(HINSTANCE, int) 
// 
//   PURPOSE: Saves instance handle and creates main window 
// 
//   COMMENTS: 
// 
//        In this function, we save the instance handle in a global variable and 
//        create and display the main program window. 
// 
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 
{ 
   HWND hWnd; 
 
   hInst = hInstance; // Store instance handle in our global variable 
 
   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 
 
   if (!hWnd) 
   { 
      return FALSE; 
   } 
 
   ShowWindow(hWnd, nCmdShow); 
   UpdateWindow(hWnd); 
 
   return TRUE; 
} 
 
// 
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) 
// 
//  PURPOSE:  Processes messages for the main window. 
// 
//  WM_COMMAND	- process the application menu 
//  WM_PAINT	- Paint the main window 
//  WM_DESTROY	- post a quit message and return 
// 
// 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
	int wmId, wmEvent; 
	PAINTSTRUCT ps; 
	HDC hdc; 
 
	switch (message) 
	{ 
	case WM_COMMAND: 
		wmId    = LOWORD(wParam); 
		wmEvent = HIWORD(wParam); 
		// Parse the menu selections: 
		switch (wmId) 
		{ 
		case ID_FILE_BMPINFO: 
			LoadBmpFile(hWnd,BmpFileName); 
			break; 
		case IDM_ABOUT: 
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 
			break; 
		case IDM_EXIT: 
			DestroyWindow(hWnd); 
			break; 
		default: 
			return DefWindowProc(hWnd, message, wParam, lParam); 
		} 
		break; 
	case WM_PAINT: 
		hdc = BeginPaint(hWnd, &ps); 
		// TODO: Add any drawing code here... 
		EndPaint(hWnd, &ps); 
		break; 
	case WM_DESTROY: 
		PostQuitMessage(0); 
		break; 
	default: 
		return DefWindowProc(hWnd, message, wParam, lParam); 
	} 
	return 0; 
} 
 
// Message handler for about box. 
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
	UNREFERENCED_PARAMETER(lParam); 
	switch (message) 
	{ 
	case WM_INITDIALOG: 
		return (INT_PTR)TRUE; 
 
	case WM_COMMAND: 
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
		{ 
			EndDialog(hDlg, LOWORD(wParam)); 
			return (INT_PTR)TRUE; 
		} 
		break; 
	} 
	return (INT_PTR)FALSE; 
} 
 
 
BOOL LoadBmpFile (HWND hWnd,char *BmpFileName) 
{    
    HFILE               hf; //文件句柄 
    LPBITMAPINFOHEADER  lpImgData; //指向BITMAPINFOHEADER结构的指针 
    LOGPALETTE          *pPal; //指向逻辑调色板结构的指针 
    LPRGBQUAD           lpRGB; //指向RGBQUAD结构的指针 
    HLOCAL              hPal; //存储调色板的局部内存句柄 
    DWORD  	    	    LineBytes;  //每一行的字节数 
    DWORD 	    	    ImgSize;   //实际的图象数据占用的字节数 
    DWORD               NumColors; //实际用到的颜色数 ,即调色板数组中的颜色个数 
    DWORD               i; 
	int					gray;	// 图像灰度值 
 
	char msg_content[102400] = ""; 
	char msg_tmp[102400] = ""; 
 
    if((hf=_lopen(BmpFileName,OF_READ))==HFILE_ERROR){ 
		sprintf(msg_tmp,"bmp file: %s can not be found! \n", BmpFileName); 
		strcpy(msg_content, msg_tmp); 
		Message_Box(hWnd, msg_content); 
        return FALSE; //打开文件错误,返回 
    } 
 
    //将BITMAPFILEHEADER结构从文件中读出,填写到bf中 
    _lread(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));  
    //将BITMAPINFOHEADER结构从文件中读出,填写到bi中 
    _lread(hf,(LPSTR)&bi,sizeof(BITMAPINFOHEADER)); 
 
	sprintf(msg_tmp,"the infomation of bitmap :\n\ 
File Size     :%-8d\ 
File Type     :%-8d\ 
Offbits       :%-8d\ 
Width         :%-8d\n\ 
Heigth        :%-8d\ 
Bit Count     :%-8d\ 
Compression   :%-8d\ 
Image Size    :%-8d\n\ 
XPelsPerMeter :%-8d\ 
YPelsPerMeter :%-8d\ 
ClrUsed       :%-8d\ 
ClrImportant  :%-8d\n", 
				bf.bfSize, 
				bf.bfType, 
				bf.bfOffBits, 
				bi.biWidth, 
				bi.biHeight, 
				bi.biBitCount, 
				bi.biCompression, 
				bi.biSizeImage, 
				bi.biXPelsPerMeter, 
				bi.biYPelsPerMeter, 
				bi.biClrUsed, 
				bi.biClrImportant); 
	strcpy(msg_content, msg_tmp); 
 
    //LineBytes为每一行的字节数 
    LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount); 
    //ImgSize为实际的图象数据占用的字节数 
    ImgSize=(DWORD)LineBytes*bi.biHeight; 
    //NumColors为实际用到的颜色数 ,即调色板数组中的颜色个数 
    if(bi.biClrUsed!=0) 
        NumColors=(DWORD)bi.biClrUsed; //如果bi.biClrUsed不为零,就是本图象实际            
    //用到的颜色数 
    else //否则,用到的颜色数为2的biBitCount次方 
        switch(bi.biBitCount){ 
       	case 1: 
            NumColors=2; 
            break; 
        case 4: 
            NumColors=16; 
            break; 
        case 8: 
            NumColors=256; 
            break; 
        case 24: 
            NumColors=0; //对于真彩色图,没用到调色板 
            break; 
        default: 
            //不处理其它的颜色数,认为出错。 
			strcpy(msg_content, "Invalid color numbers! \n"); 
			Message_Box(hWnd, msg_content); 
            _lclose(hf); 
            return FALSE; //关闭文件,返回FALSE 
        } 
 
    if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+ 
        sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER))) 
    { 
        //计算出的偏移量与实际偏移量不符,一定是颜色数出错 
		strcpy(msg_content, "Invalid color numbers! \n"); 
		Message_Box(hWnd, msg_content); 
        _lclose(hf); 
     	return FALSE; //关闭文件,返回FALSE 
  	} 
  	  
    bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors 
        *sizeof(RGBQUAD)+ImgSize; 
 
    //分配内存,大小为BITMAPINFOHEADER结构长度加调色板+实际位图数据 
  	if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+ 
        NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL) 
    { 
		//分配内存错误 
		strcpy(msg_content, "Error alloc memory! \n"); 
		Message_Box(hWnd, msg_content); 
   		_lclose(hf); 
    	return FALSE; //关闭文件,返回FALSE 
    } 
 
  	//指针lpImgData指向该内存区 
  	lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);  
 
  	//文件指针重新定位到BITMAPINFOHEADER开始处 
  	_llseek(hf,sizeof(BITMAPFILEHEADER),SEEK_SET); 
 
  	//将文件内容读入lpImgData 
  	_hread(hf,(char *)lpImgData,(long)sizeof(BITMAPINFOHEADER) 
        +(long)NumColors*sizeof(RGBQUAD)+ImgSize); 
  	_lclose(hf); //关闭文件 
 
 	if(NumColors!=0) //NumColors不为零,说明用到了调色板 
  	{                     
    	//为逻辑调色板分配局部内存,大小为逻辑调色板结构长度加NumColors个          
    	//PALETTENTRY大小 
   		hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) +  
   		    NumColors* sizeof(PALETTEENTRY)); 
 
        //指针pPal指向该内存区 
    	pPal =(LOGPALETTE *)LocalLock(hPal); 
 
     	//填写逻辑调色板结构的头 
     	pPal->palNumEntries = NumColors; 
     	pPal->palVersion    = 0x300; 
 
     	//lpRGB指向的是调色板开始的位置 
     	lpRGB = (LPRGBQUAD)((LPSTR)lpImgData + (DWORD)sizeof(BITMAPINFOHEADER)); 
 
     	//填写每一项 
     	for (i = 0; i < NumColors; i++) 
     	{ 
            pPal->palPalEntry[i].peRed=lpRGB->rgbRed; 
            pPal->palPalEntry[i].peGreen=lpRGB->rgbGreen; 
            pPal->palPalEntry[i].peBlue=lpRGB->rgbBlue; 
			pPal->palPalEntry[i].peFlags=(BYTE)0; 
			// 灰度值计算方法0.3Red+0.59Green+0.11Blue  
			gray=(lpRGB->rgbRed)*0.3+(lpRGB->rgbGreen)*0.59+(lpRGB->rgbBlue)*0.11; 
            if ( i%1 == 0)  
			{ 
				strcpy(msg_tmp, ""); 
				sprintf(msg_tmp,"[%-3d]:R = %-3d,G = %-3d,B = %-3d,G = %-3d ",\ 
					i, 
					pPal->palPalEntry[i].peRed, 
					pPal->palPalEntry[i].peGreen, 
					pPal->palPalEntry[i].peBlue, 
					gray); 
			strcat(msg_content, msg_tmp); 
			} 
			if ( (i+1)%4 == 0)  
				strcat(msg_content, "\n"); 
            lpRGB++; //指针移到下一项 
        } 
 
        //释放局部内存 
        LocalUnlock(hPal); 
        LocalFree(hPal); 
    } 
 
    GlobalUnlock(hImgData); //解锁内存区 
	Message_Box(hWnd, msg_content); 
 
    return TRUE; //成功返回 
} 
 
// Show the Message 
void Message_Box(HWND hWnd, char content[]) 
{ 
	WCHAR wchar_outstring[102400]; 
	swprintf(wchar_outstring, L"%S", content); 
	LPCWSTR p_outstring = wchar_outstring; 
 
	WCHAR wchar_outtitle[255]; 
	swprintf(wchar_outtitle, L"%S", "Message Box"); 
	LPCWSTR p_outtitle = wchar_outtitle; 
 
	MessageBox(hWnd, p_outstring, p_outtitle, MB_OK); 
}