一般的圖像處理軟件都對讀入程序的圖像文件建一個縮略圖的列表,像ACDSee那樣。筆者最近在做一個圖像處理的項目,處理的原始數據就是圖像文件。從項目一開始就想做一個縮略圖,但一直苦於技術水平有限,且時間也不允許。最近兩天閑暇之余就Google,百度了一下,仔細研究了一下縮略圖的實現方法。其實用VC++實現一個縮略圖的思想並不復雜。就是分兩步:1.創建CListCtrl控件和CImageList圖像列表,設置各自的相應屬性。2.將你要顯示的圖像文件的縮略圖做好,並制成位圖文件加入到CImageList中,然后將每個圖像文件設置成一個Item插入到CListCtrl中就完成了縮略的的制作。剩下的你就可以寫各個消息的處理方法,以響應你對縮略圖的操作。
說起來簡單,但當筆者親自實現時卻遇到了許多的麻煩,最大的麻煩就是如何在內存里制作縮略圖,如何將各個圖像文件的縮略圖制成Bitmap位圖資源(因為CImageList只能加入位圖資源)。筆者在內存中操作了半天,最后還是沒成功。而且最大的問題是在內存中由於調色板的原因,在內存中畫好的圖像是黑白的。最后我想到了我們這個項目中應用的CXImage圖像處理庫了。我仔細的讀了一下這個庫的文檔,正所謂“踏破鐵鞋無覓處,得來全不費工夫”,我發現可以基於這個庫提供的方法,很簡單的實現縮略圖。原理還是這個原理,只是應用CXImage后,原來的問題一一化解,原來的操作也更簡單了。下面就把實現的過程及代碼貼出來,以饗讀者。
程序所達到的效果:
1.創建CListCtrl控件和CImageList圖像列表,設置各自的相應屬性。對於我的程序我是在圖中左面的視圖的OnCreate中動態創建的CListCtrl控件和CImageList圖像列表的。
- int CWorkspaceBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
- {
- if (CBCGPDockingControlBar::OnCreate(lpCreateStruct) == -1)
- return -1;
- CRect rectDummy;
- rectDummy.SetRectEmpty ();
- // Create tree windows.
- //動態生產列表控件和圖像列表
- m_ListCtl.Create(LVS_ICON|WS_CHILD | WS_VISIBLE|LVS_TYPEMASK,
- CRect(0,0,150,500),this,100);
- m_MyImageList.Create(64,64,ILC_COLOR24, 0, 1);
- return 0;
- }
2.設計一個左面視圖的方法,使我們可以在文檔類中調用這個方法為左面視圖添加Items,這其中要完成的任務還有在內存中做好每個圖像文件的Bitmap(位圖資源)。
代碼如下:
- void CWorkspaceBar::InitialListCtrl(int imageCount,CString *pImageNameList)
- //根據讀入的文檔數據初始化列表控件
- //傳入參數imageCount是圖像文件的總數,pImageNameList是各個圖像文件按順序的名字列表
- {
- //保存文檔的數據
- m_imageCount=imageCount;
- m_pImageNameList=pImageNameList;
- //應用CXImage在內存中動態生產指定大小的位圖
- CxImage image; //聲明CXImage對象
- for (int i=0;i<imageCount;i++)
- {
- //應用CXImage載入圖像,本程序是相對路徑
- image.Load(pImageNameList[i],CXIMAGE_FORMAT_BMP);
- //應用CXImage將圖像變成我們指定的大小即96*96的,前面聲明CImageList時就是96*96的
- image.Resample(96,96,2);
- //應用CXImage在內存中生產位圖
- CDC *pDC = GetDC();
- HBITMAP hBit=image.MakeBitmap(pDC->GetSafeHdc());
- CBitmap bmp;
- bmp.Attach(hBit);
- //將位圖加到圖像列表中
- m_MyImageList.Add(&bmp,RGB(255, 255, 255));
- bmp.Detach();
- }
- //將圖像列表與列表控件關聯起來
- m_ListCtl.SetImageList(&m_MyImageList, LVSIL_NORMAL);
- //設置列表控件各項
- LVITEM item;
- item.mask=LVIF_TEXT|LVIF_IMAGE;
- item.iItem=0; // 第1項
- item.iSubItem=0; // 主項
- item.pszText="";
- item.iImage=0; // 設置關聯圖像列表中指定圖像的索引值
- m_ListCtl.InsertItem(&item); // 添加第1項
- m_ListCtl.SetItemText(0,0,pImageNameList[0]);
- for (i=1;i<imageCount;i++)
- {
- item.iItem=i; // 准備添加項
- item.iImage=i;
- m_ListCtl.InsertItem(&item);
- m_ListCtl.SetItemText(i,0,pImageNameList[i]);
- }
- DWORD dwOldStyle,dwNewStyle;
- dwNewStyle = LVS_ICON;
- HWND hWndLt=m_ListCtl.GetSafeHwnd(); // 獲得列表視圖控件的窗口句柄
- dwOldStyle=GetWindowLong(hWndLt, GWL_STYLE); // 獲得列表視圖控件的窗口風格
- if((dwOldStyle & LVS_TYPEMASK)!=LVS_ICON) // 判斷當前的顯示方式是不是所指定的方式
- {
- dwOldStyle &=~LVS_TYPEMASK; // 從舊的窗口風格中屏蔽不必要的信息
- dwNewStyle |=dwOldStyle; // 保持窗口其它風格不變,僅改變顯示方式
- SetWindowLong(hWndLt, GWL_STYLE, dwNewStyle); // 改變列表控件窗口風格
- }
- }
剩下的工作就是寫各個消息的處理方法了,包括點擊相應縮略圖在對應的視圖里顯示各個圖像等等。
總結:本程序是基於CXImage影像處理庫做的。CXImage是一個很好的圖像處理庫,在網上可以很容易下到,而且是開源的。筆者認為CXImage要優於GDI、GDI+。本程序在VC++6.0中調試通過,運行良好。