65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (72投票s)

2003 年 9 月 25 日

4分钟阅读

viewsIcon

381327

downloadIcon

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;
}
/////

其中 ImageFlagsNoneImageFlags 枚举的一部分,表示没有可用的格式信息。

关键是,在选择要加载到文件列表(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 的缩略图查看器”提醒我写这篇论文。祝你好运!

© . All rights reserved.