将数组中的RGBA序列绘制出来——GDI、MFC_GDI、GDI+实现

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/CharlesSimonyi/article/details/17242485

如果你有一个字节数组,里面存放着R/G/B/A颜色值序列,如何将它所表示的图片绘制在窗口上呢?

之前在论坛上看到有人提了这么一个问题:http://bbs.csdn.net/topics/390663627

这个用GDI、MFC封装的GDI、GDI+均可实现。不过要注意的是内存中的R、G、B、A顺序得调整下,调整为B、G、R、A。因为这是windowsGDI内部使用的顺序。

还有,GDI不支持透明通道A,透明通道A的值读进去以后不起作用。

欲支持透明通道,应使用GDI+实现。

GDI实现:

//参数2、3:图片绘制在目标窗口上的位置,即图片左上角在窗口上的坐标,比如(0,0)
void DrawBitmap(HWND hwnd, int x, int y, int nBmpWidth, int nBmpHeight,const unsigned char *pBmpData)
{
	HBITMAP hBitmap = ::CreateBitmap(nBmpWidth, nBmpHeight, 1, 32, pBmpData);
	HDC hWndDc = ::GetDC(hwnd);
	HDC hMemDc = ::CreateCompatibleDC(hWndDc);
	HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDc, hBitmap);
	::BitBlt(hWndDc, x, y, nBmpWidth, nBmpHeight, hMemDc, 0, 0, SRCCOPY);

	::SelectObject(hMemDc, hOldBitmap);
	::DeleteObject(hBitmap);
	::DeleteDC(hMemDc);
	::ReleaseDC(hwnd, hWndDc);
}


 MFC封装的GDI实现:

//参数2、3:图片绘制在目标窗口上的位置,即图片左上角在窗口上的坐标,比如(0,0)
void DrawBitmap(CWnd *pWnd, int x, int y, int nBmpWidth, int nBmpHeight,const unsigned char *pBmpData)
{
	CBitmap bitmap;CDC MemDc;
	bitmap.CreateBitmap(nBmpWidth, nBmpHeight, 1, 32, pBmpData);
	CDC *pWndDc = pWnd->GetDC();
	MemDc.CreateCompatibleDC(pWndDc);
	CBitmap *pOldBitmap = MemDc.SelectObject(&bitmap);
	pWndDc->BitBlt(x, y, nBmpWidth, nBmpHeight, &MemDc, 0, 0, SRCCOPY);

	MemDc.SelectObject(pOldBitmap);
	pWnd->ReleaseDC(pWndDc);pWndDc = NULL;
}


 GDI+实现:

#include <GdiPlus.h>
#pragma comment(lib,"Gdiplus.lib")
using namespace Gdiplus;

//该类主要用来在程序启动时自动执行GdiplusStartup,程序结束时执行GdiplusShutdown
//使得GDI+可以正常工作,也可以不定义该类,而在自己的代码中自行调用GdiplusStartup和GdiplusShutdown
class GdiPlusInit
{
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	GdiPlusInit()
	{
		GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
	}
	~GdiPlusInit()
	{
		GdiplusShutdown(gdiplusToken);
	}
	static GdiPlusInit Instance;
};

GdiPlusInit GdiPlusInit::Instance;


//参数2、3:图片绘制在目标窗口上的位置,即图片左上角在窗口上的坐标,比如(0,0)
void DrawBitmap(HWND hwnd, int x, int y, int nBmpWidth, int nBmpHeight,unsigned char *pBmpData)
{
	Bitmap bitmap(nBmpWidth, nBmpHeight, nBmpWidth * 4, PixelFormat32bppARGB, pBmpData);
	Graphics gps(hwnd);
	gps.DrawImage(&bitmap, x, y);
}


 这些只是个简单的例子,没有做错误处理,在实际使用时注意错误处理。

 

可见MFC对GDI的封装,并没有使我们的开发变的更简单。
不过值得注意的是两个需要释放内存的地方,由对象的析构函数帮我们完成了,减少了因疏忽而带来的内存泄露、GDI对象泄露问题的发生率。

而GDI+更加面向对象,代码编更简单,并且内存释放、GDI对象释放大多由它负责,进一步减少了因程序员疏忽而带来的内存泄露、GDI对象泄露问题的发生率。

 

 使用上述GDI+代码,在一个循环中不断递增透明通道值并绘制的效果:

MSDN上的GDI+文档:http://msdn.microsoft.com/en-us/library/windows/desktop/ms533799(v=vs.85).aspx

猜你喜欢

转载自blog.csdn.net/CharlesSimonyi/article/details/17242485