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

来源:互联网 发布:遨龙一号知乎 编辑:程序博客网 时间:2024/06/12 21:46

如果你有一个字节数组,里面存放着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和GdiplusShutdownclass 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

2 0
原创粉丝点击