编写一个图像处理类的程序,实现缩略图是非常自然的想发。基于mfc+opencv框架,实现以下代码
style child border none
一、填写界面 主要实现图片的添加、删除、显示
左边是listctrl控件(alignment为top),右边是textbox控件(client edge 为true)。textbox控件主要用来占个位置,具体显示的时候要进行重载处理。
二、实现缩略图
1)最方便使用的缩略图函数是Gdiplus下的 GetThumbnailImage函数
Bitmap* pThumbnail = static_cast<Bitmap*>(img.GetThumbnailImage(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, NULL, NULL));
能够将大图转换为小图。为了使用Gdiplus,首先需要引入和初始化
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")
ULONG_PTR GdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
在initdialog中
GdiplusStartup(&GdiplusToken, &gdiplusStartupInput, NULL);
2)添加图片函数,主要是将文件目录名push到m_VectorImageNames结构中
void CGOthumbnailDlg::OnBnClickedButtonAddimg()
{
CString szFilters= _T("*(*.*)|*.*|jpg(*.jpg)|*.jpg|bmp(*.bmp)|*.bmp||");
CFileDialog dlgFile(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilters,NULL,0,TRUE);
CString FilePathName ;
if(dlgFile.DoModal()==IDOK){
FilePathName = dlgFile.GetPathName();
}
m_VectorImageNames.push_back(FilePathName);
DrawThumbnails();
}
3)为了图片保存在imagelist中,并且使用listctrl控件进行显示,并且在初始化的时候进行定义
m_ImageListThumb.Create(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, ILC_COLOR24, 0, 1);
m_ListThumbnail.SetImageList(&m_ImageListThumb, LVSIL_NORMAL);
m_nSelectedItem = 0;
具体绘图函数
void CGOthumbnailDlg::DrawThumbnails(void)
{
CBitmap* pImage = NULL;
HBITMAP hBmp = NULL;
POINT pt;
CString strPath;
// no images
if (m_VectorImageNames.empty())
return;
//不自动刷新
m_ListThumbnail.SetRedraw(FALSE);
// reset our image list
for (int i = 0; i<m_ImageListThumb.GetImageCount(); i++)
m_ImageListThumb.Remove(i);
// remove all items from list view
if (m_ListThumbnail.GetItemCount() != 0)
m_ListThumbnail.DeleteAllItems();
// set the size of the image list
m_ImageListThumb.SetImageCount(m_VectorImageNames.size());
// draw the thumbnails
for (int i = 0;i<m_VectorImageNames.size();i++)
{
USES_CONVERSION;
Bitmap img( m_VectorImageNames[i].AllocSysString());
//使用GDI直接获得thumbnail
Bitmap* pThumbnail = static_cast<Bitmap*>(img.GetThumbnailImage(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, NULL, NULL));
// attach the thumbnail bitmap handle to an CBitmap object
pThumbnail->GetHBITMAP(NULL, &hBmp);
pImage = new CBitmap();
pImage->Attach(hBmp);
m_ImageListThumb.Replace(i, pImage, NULL);
m_ListThumbnail.InsertItem(i, m_VectorImageNames[i], i);
delete pImage;
delete pThumbnail;
}
//显示thumbnail
m_ListThumbnail.SetRedraw();
}
4)点击图片能够显示大图
void CGOthumbnailDlg::OnNMClickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
// retrieve message info.
LPNMITEMACTIVATE pItemAct = (LPNMITEMACTIVATE)pNMHDR;
// determine which item receives the click
LVHITTESTINFO hitTest;
ZeroMemory(&hitTest, sizeof(LVHITTESTINFO));
hitTest.pt = pItemAct->ptAction;
m_ListThumbnail.SendMessage(LVM_SUBITEMHITTEST, 0, (LPARAM)&hitTest);
// draw the selected image
if ( hitTest.iItem >= 0)
{
m_nSelectedItem = hitTest.iItem;
DrawSelectedImage();
}
// select the item clicked
*pResult = 0;
}
void CGOthumbnailDlg::DrawSelectedImage(void)
{
CString strPath;
Rect DesRect;
RECT clRect;
USES_CONVERSION;
Image img(m_VectorImageNames[m_nSelectedItem].AllocSysString() );
// get destination rectangle
m_imagerect.GetClientRect(&clRect);
DesRect.X = clRect.left;
DesRect.Y = clRect.top;
DesRect.Width = clRect.right - clRect.left;
DesRect.Height = clRect.bottom - clRect.top;
// draw the image
Graphics gc( m_imagerect.GetDC()->GetSafeHdc() );
gc.DrawImage(&img, DesRect);
}
5)重载textbox的基类,改为imagearea类,主要是重载paint函数
void CImageArea::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CGOthumbnailDlg* pWnd = static_cast<CGOthumbnailDlg*>(GetParent());
if(pWnd->m_ListThumbnail.GetItemCount() != 0)
pWnd->DrawSelectedImage();
// Do not call CStatic::OnPaint() for painting messages
}
三、实现结果和小结
这个程序看似只是解决一个简单的问题,但是涉及到的东西很多。能够比较好的解决关键是找到了比较好的参考代码。同时也是因为我在很久之前就发现了这个问题,并且积极地去寻找解决方法。这两点应该都是最后得到比较好的结果必不可少的。
下一步就是需要把这样的程序进行整理整合,更好方便复用。