WEB开发网
开发学院软件开发VC 使用GDI+进行图像处理 阅读

使用GDI+进行图像处理

 2008-02-26 20:26:59 来源:WEB开发网   
核心提示:在此代码段中,重点是GDI+要用宽字符串,使用GDI+进行图像处理(2),所以你要用USES_CONVERSION 和 A2W.,原来的CPicture用Load函数从某个CFile、CArchive、资源ID或流中加载图像,对于象视频或高端图像编辑等图形敏感的应用程序你可能不会用GDI+来编程(一般都用DirectX

 在此代码段中,重点是GDI+要用宽字符串,所以你要用USES_CONVERSION 和 A2W.。原来的CPicture用Load函数从某个CFile、CArchive、资源ID或流中加载图像。所有Load函数最终都走到从流中加载图像的例程:CPicture::Load(IStream*)。当我开始用Image代替IPicture,并用GDI+函数从流中加载数据时,它不工作。情况真是很糟,令人沮丧。问题出在MFC的CArchiveStream类,这个类在CArchive类之上实现流化。可能是CArchiveStream没有正确实现所有的IStream方法,Image::FromStream无法正确处理基于CArchiveStream的流操作,更糟的是它返回一切OK,但实际上当你试图显示或者删除Image时会失败。 为了解决这个问题,我重写了CPicture::Load(UINT nID),其中用到了CreateStreamOnHGlobal函数。这个API函数很好用,它在一个全局内存块中创建一个流:

// 分配全局内存并在其中创建流
HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
memcpy(pmem,lpRsrc,len);
IStream* pstm;
CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);

 这里lpRsrc已经指向内存中的图形资源。所以基本思路是加载图像资源,将它拷贝到全局内存中,在内存上创建一个流,然后用Image::FromStream创建一个图象,有关细节请参见例子源代码。当对象被销毁或某人加载另外的图像时,CPicture自动释放全局内存。对于从CFile或者CArchive加载的情况——其实,根本不需要考虑这种情况。 以上是加载的方法,下面看看如何显示图像,你必须使用GDI+类Graphics——与原来GDI中的设备上下文(HDC或CDC)类似,它也有一个方法DrawImage:

BOOL CPicture::Render(CDC* pDC, CRect rc) const
{
…….
 Graphics graphics(pDC->m_hDC);
 graphics.DrawImage(m_pImage,
  rc.left, rc.top, rc.Width(), rc.Height());
}   
  有关细节请参考源代码。用Image代替IPicture来表现图像要简单一些。Image::GetWidth 和Image::GetHeight分别获得象素的宽度和高度,这正是你所需要代替IPicture中HIMETRIC单位的东东。一般来说,用GDI+很容易编程,例如下面示范了如何旋转: void CPicture::Rotate(RotateFlipType rft)
{
 if (m_pImage) {
  m_pImage->RotateFlip(rft);
 }
}

这个代码将图像顺时针旋转90度,下面列出了RotateFlipType所有可能的情况: RotateFlipType 选项 // 用于Image::RotateFlip的枚举类型
enum RotateFlipType
{
  RotateNoneFlipNone = 0,
  Rotate90FlipNone  = 1,
  Rotate180FlipNone = 2,
  Rotate270FlipNone = 3,
  RotateNoneFlipX  = 4,
  Rotate90FlipX   = 5,
  Rotate180FlipX   = 6,
  Rotate270FlipX   = 7,
  RotateNoneFlipY  = Rotate180FlipX,
  Rotate90FlipY   = Rotate270FlipX,
  Rotate180FlipY   = RotateNoneFlipX,
  Rotate270FlipY   = Rotate90FlipX,
  RotateNoneFlipXY  = Rotate180FlipNone,
  Rotate90FlipXY   = Rotate270FlipNone,
  Rotate180FlipXY  = RotateNoneFlipNone,
  Rotate270FlipXY  = Rotate90FlipNone
};

 GDI+ 的其它函数用于展开和修剪图像,它甚至还有一个函数Image::GetThumbnailImage用来解决缩略图问题,有兴趣的话不妨自己试一下。 我鼓励大家去研究一下GDI+。有些程序员因为它速度慢而不喜欢它,但是有很多文档中提供了一些技巧来改善它的性能。例如,有一个类叫CachedBitmap,这个类以优化设备的格式保存位图。对于象视频或高端图像编辑等图形敏感的应用程序你可能不会用GDI+来编程(一般都用DirectX),但对于日常的一般图形应用来说,GDI+不失为一种比GDI更好的选择。

上一页  1 2 

Tags:使用 GDI 进行

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接