读取BMP图片并显示到窗口.

//
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <fstream>
#include <string>
#include "define.h"
using namespace std;

LPCWSTR szClass = TEXT("test1001");
LPCWSTR szTitle = TEXT("BMP");


//窗口过程
LRESULT CALLBACK __WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
/*********************************************************************************
其它部分
**********************************************************************************/

int biWidth;  //图像宽
int biHeight;  //图像高
int biBitCount; //图像类型,每像素位数
//RGBQUAD *pColorTable;  //颜色表指针
unsigned char *pBmpBuf;  //存储图像数据
int lineByte;         //图像数据每行字节数
/**
* 函数名: readBmp
* 参  数: bmpName -- bmp文件名
* 功  能: 读入bmp文件,并获取相应的信息
*/
bool readBmp(char *bmpName)
{
	FILE *fp;
	if ((fp = fopen(bmpName, "rb")) == NULL)  //以二进制的方式打开文件
	{
		cout << "The file " << bmpName << "was not opened" << endl;
		return FALSE;
	}
	if (fseek(fp, sizeof(BITMAPFILEHEADER), SEEK_CUR))  //跳过BITMAPFILEHEADE
	{
		cout << "跳转失败" << endl;
		return FALSE;
	}
	BITMAPINFOHEADER infoHead;
	fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);   //从fp中读取BITMAPINFOHEADER信息到infoHead中,同时fp的指针移动
	biWidth = infoHead.biWidth;
	biHeight = infoHead.biHeight;
	biBitCount = infoHead.biBitCount;
	lineByte = (biWidth*biBitCount / 8 + 3) / 4 * 4;   //lineByte必须为4的倍数
	//24位bmp没有颜色表,所以就直接到了实际的位图数据的起始位置
	pBmpBuf = new unsigned char[lineByte * biHeight];
	fread(pBmpBuf, sizeof(char), lineByte * biHeight, fp);
	fclose(fp);   //关闭文件
	return TRUE;
}
/**
* 函数名: saveBmp
* 参  数: bmpName -- bmp文件名
* 功  能: 将bmp位图文件的相关信息,写入新创建的文件中
*/
bool saveBmp(char *bmpName)
{
	FILE *fp;
	if ((fp = fopen(bmpName, "wb")) == NULL)   //以二进制写入方式打开
	{
		printf("打开文件失败");
		return FALSE;
	}
	//设置BITMAPFILEHEADER参数
	BITMAPFILEHEADER fileHead;
	fileHead.bfType = 0x4D42;
	fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + lineByte * biHeight;
	fileHead.bfReserved1 = 0;
	fileHead.bfReserved2 = 0;
	fileHead.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
	//设置BITMAPINFOHEADER参数
	BITMAPINFOHEADER infoHead;
	infoHead.biSize = 40;
	infoHead.biWidth = biWidth;
	infoHead.biHeight = biHeight;
	infoHead.biPlanes = 1;
	infoHead.biBitCount = biBitCount;
	infoHead.biCompression = BI_RGB;
	infoHead.biSizeImage = lineByte * biHeight;
	infoHead.biXPelsPerMeter = 0;
	infoHead.biYPelsPerMeter = 0;
	infoHead.biClrUsed = 0;
	infoHead.biClrImportant = 0;
	//写入
	fwrite(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);
	fwrite(pBmpBuf, sizeof(char), lineByte * biHeight, fp);
	fclose(fp);    //关闭文件
	return TRUE;


}
void DeleteBmp()
{
	delete[]pBmpBuf;  //释放内存
}
/**
* 函数名: work
* 功  能: 处理位图信息,并将位图数据保存到ImageData文件中
*/
void work(char* filename)
{
//	char readFileName[] = "test.BMP";   //定义要读入的文件名
//	if (FALSE == readBmp(readFileName))
	if (false == readBmp(filename))
		printf("read file error!\n");

	//输出图像的信息
	cout << "Width = " << biWidth << " Height = " << biHeight << " biBitCount=" << biBitCount << endl;
	
}


//GDI部分,绘图

HDC g_hdc, g_mdc, g_bufdc;
HBITMAP bmps[2];//0 是down  1 是背景
//显示相关初始化
void DeviceInit(HWND hwnd)//, LPCWSTR bmpname
{
	HBITMAP bmp;
	g_hdc = GetDC(hwnd);
#if(1)
	g_mdc = CreateCompatibleDC(g_hdc);
	g_bufdc = CreateCompatibleDC(g_hdc);//再创建一个和hdc兼容的缓冲DC
	bmp = CreateCompatibleBitmap(g_hdc, biWidth, biHeight); //建一个和窗口兼容的空的位图对象
	SelectObject(g_mdc, bmp);

	//载入资源
//	bmps[0] = (HBITMAP)LoadImage(NULL,bmpname, IMAGE_BITMAP, 40, 40, LR_LOADFROMFILE);
	HFONT hFont = CreateFont(20, 0, 0, 0, 700, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, TEXT("微软雅黑"));
	SelectObject(g_mdc, hFont);
	SetBkMode(g_mdc, TRANSPARENT);    //设置文字显示背景透明
	SetTextColor(g_mdc, RGB(0, 0, 0));
#endif
}
//显示
void DeviceDisplay(unsigned char* bmpda)
{
	
	wchar_t strings[100];
	COLORREF rgba;
	RGB_t rgb_t;
	unsigned char *pbmpdata = bmpda;
	for (int i = 0;i<biHeight; i++)
	{
		for (int j = 0; j < biWidth;j++)
		{
<span style="white-space:pre">			</span>//这里比较关键了,
<span style="white-space:pre">			</span>//1:BMP文件24位颜色 存储顺序BGR;2:3*j表示每个像素占三个UCHAR 
			int b = *(pbmpdata + (biHeight - 1 - i)*lineByte + 3 * j + 0);
			int g = *(pbmpdata + (biHeight - 1 - i)*lineByte + 3 * j + 1);
			int r = *(pbmpdata + (biHeight - 1 - i)*lineByte + 3 * j + 2);
			int a = 0;
		//	rgba = (((r)+((g) << 8)) + (((b) << 16) + ((a) << 24)));
			SetPixel(g_mdc, j, i, (((r)+((g) << 8)) + (((b) << 16) + ((a) << 24))));
		//	SetPixel(g_hdc, j, i, rgba);
		//	SetPixel(g_hdc, j, i, RGB(r, g, b));

		}
	}
	BitBlt(g_hdc, 0, 0, biWidth, biHeight, g_mdc, 0, 0, SRCCOPY);

}
/**********************************************************************************/
int main(int argc, char *argv[])
{
	if (argc < 2)
		work("test.bmp");
	else
		work(argv[1]);

	HINSTANCE hIns = ::GetModuleHandle(0);
	WNDCLASSEX wc;
	wc.cbSize = sizeof(wc);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hIns;
	wc.hIcon = LoadIcon(0, IDI_APPLICATION);
	wc.hIconSm = 0;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.hCursor = LoadCursor(0, IDC_ARROW);
	wc.lpfnWndProc = __WndProc;
	wc.lpszMenuName = NULL;
	wc.lpszClassName = szClass;

	if (!RegisterClassEx(&wc)) exit(0);

//	DWORD style = WS_OVERLAPPEDWINDOW;
	//细边框窗口
	DWORD style = WS_POPUP | WS_THICKFRAME;
	DWORD styleEx = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;

	//根据图片大小生成窗口
	RECT rect;
	if ((biWidth!=0)&&(biHeight!=0))
		rect = { 0, 0,biWidth,biHeight };
	else
		rect = { 0, 0, 800, 600 };
	AdjustWindowRectEx(&rect, style, false, styleEx);

	HWND hWnd = CreateWindowEx(styleEx, szClass, szTitle, style, 0, 0,
		rect.right - rect.left, rect.bottom - rect.top, 0, 0, hIns, 0);
	if (hWnd == 0) exit(0);

	UpdateWindow(hWnd);
	ShowWindow(hWnd, SW_SHOW);

	//TODO, init this

	DeviceInit(hWnd);

	MSG msg = { 0 };
	while (msg.message != WM_QUIT) {
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else {
			//TODO, do this
			DeviceDisplay(pBmpBuf);
			
		}
	}

	return 0;
}

LRESULT CALLBACK __WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;
	switch (msg) {
	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		
		EndPaint(hWnd, &ps);
		break;

	case WM_KEYDOWN:
		switch (wParam) {
		case VK_ESCAPE:     //按Esc键退出程序
			PostQuitMessage(0);
			break;
		}
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}






相关参考:

1窗口创建:

http://www.oschina.net/code/snippet_146803_51275

2BMP文件读取:

http://blog.csdn.net/sun1956/article/details/8648460

你可能感兴趣的:(算法,bmp,gdi)