使用 GDI+ 和 MFC 的缩略图查看器和图像处理






4.93/5 (72投票s)
2003 年 9 月 25 日
4分钟阅读

381327

24916
使用 GDI+ 和 MFC 创建缩略图图像查看器和一些处理函数。
引言
我想提出一种简单的方法,使用 GDI+ 在普通的 MFC VC++ 6.0 应用程序中实现一个带有图像处理功能的图像缩略图查看器。
背景
我们的想法是仅使用 Microsoft Windows 环境中提供的功能,而不是使用许多现有的自定义图像库。
使用代码
“ImageTool”应用程序有一个显示文件夹中缩略图图像的图像查看器。此视图窗口 CImageToolView
使用 CImageList
对象,并继承自 CListView
类,其中包含加载缩略图的线程。它还有一个 CFoldersDlg
对象用于浏览计算机特定文件夹,以及另一个 CPreviewDlg
对象用于预览选定的图像,包括各种图像操作的结果。这两个对象都继承自 CDialog
类。
启动应用程序后,我们需要选择一个文件夹,然后在主视图中,如果该文件夹中有可用图像,我们将看到缩略图。从缩略图列表中选择一张图像,我们可以在预览对话框中看到原始图像。通过应用其中一项图像处理操作,我们也可以在预览对话框中看到结果。基本的图像处理操作包括:- 镜像、- 翻转、- 右转 90 度、- 左转 90 度、- 灰度、- 负片、- 伪彩色(伽马值)、- 伪阈值(透明度范围)、- 提亮、- 调暗、- 对比度、- 锐化。这些操作在 CImageToolDoc
类中的一个单独线程中实现。我们还通过 Bitmap::Clone( . )
函数实现了“撤销/重做”功能。
可以显示的图像取决于 GDI+ 支持的图形文件格式:- BMP(Windows 位图)、- EMF(增强型图元文件)、- Exif(可交换图像文件)、- GIF(图形交换格式)、- Icon(图标)、- JPEG(联合图像专家组)、- PNG(便携式网络图形)、- TIFF(标记图像文件格式)、- WMF(Windows 图元文件),基本上所有可以加载到 GDI+ Bitmap
对象中的内容。
无论如何,我们必须始终检查我们处理的是否是有效的 GDI+ 图像。使用 Bitmap::GetFlags()
函数可以很容易地做到这一点,例如:
//// BOOL CImageToolDoc::IsImageGDIPLUSValid( CString filePath ) { Bitmap image( filePath.AllocSysString() ); if( image.GetFlags() == ImageFlagsNone ) return FALSE; else return TRUE; } /////
其中 ImageFlagsNone
是 ImageFlags
枚举的一部分,表示没有可用的格式信息。
关键是,在选择要加载到文件列表(m_vFileName
)中的文件夹(CImageToolDoc::SelectDirectory( . )
)后,只显示支持的图像,包括扩展名已被修改的图像文件。RunLoadThumbnailThread
线程使用 GDI+ Bitmap
对象从此列表中加载图像文件。
这里的代码并不复杂,但我只是想指出,我没有使用 Image::GetThumbnailImage( . )
函数来获取缩略图,而是选择自己缩放位图。我这样做不是因为我不能使用
Bitmap *pThumbnail = (Bitmap*)image.GetThumbnailImage( nDestWidth, nDestHeight, NULL, NULL );
而是因为我无法直接按我想要的方式处理背景颜色,所以无论如何我都需要使用一个从图像创建的 GDI+ Graphics
对象,像这样:
Graphics *grPhoto = Graphics::FromImage( bmPhoto ); Color colorW(255, 255, 255, 255); Clear( colorW );
而且我也不想处理嵌入的缩略图图像 - 如果文件有的话 - 因为在这种情况下,GetThumbnailImage( . )
会检索嵌入的缩略图图像,而不是通过将主图像缩放到指定大小来创建缩略图图像。
在线程结束时,我必须用 MFC CBitmap
对象填充图像列表,这些对象是从已经缩放过的 GDI+ Bitmap
对象获得的。
第二个线程——图像处理线程——使用直接的 GDI+ Bitmap
图像处理函数(例如 RotateFlip( . )
)或从图像创建的 GDI+ Graphics
对象,该对象与 GDI+ ColorMatrix
结构和 GDI+ ImageAttributes
对象关联。
有些操作使用硬编码的参数,而另一些(如伽马值和透明度范围)则关联了一个对话框来指定参数。这仅用于演示目的,可以进一步改进。
我还通过 CImageToolView::OnDraw( . )
提供了“打印预览”功能,但“打印”功能需要改进。
CFoldersDlg
对象使用一个 CTreeCtrl
派生控件(CFoldersTreeCtrl
)来方便文件夹选择,CPreviewDlg
对象使用一个 CStatic
对象来显示图像。在 CPreviewDlg
中,我使用了一个内存设备上下文对象来消除闪烁。
结论
请记住,这仅用于演示目的,如果作为专业应用程序使用,需要改进,特别是在设计层面,例如验证和在多线程操作中加载图像文件。此外,还应添加“保存”和其他功能。感谢 Moah,他的文章“使用 ListCtrl 的缩略图查看器”提醒我写这篇论文。祝你好运!