摘要:本文及其附帶源碼利用GID+ Bitmap實現了將一張圖片分解為多張指定尺寸的圖片,以及將多張圖片合并為一張。
關鍵字:GDI+、圖片合并、分解
環境:VS2005/WinXP/SP2/1280*800解析度
事情的起因是這樣的:我的一個VC6工程 res 路徑下存在一些圖片,它們是在繪製 ToolBar的時候產生的,基本是多個16*16或32*32的小圖片拼湊而成的一張大圖片,我需要用到其中的某幾個小圖片,單獨存為BMP或者ICO,但是找了幾個做表徵圖的軟體,都沒有這個功能。問了罈子裡的一些朋友,好像也沒有這種簡單的現成的工具,於是一咬牙一跺腳,自己寫吧。順便把多個圖片合并也寫進去了,目前只是測試了自己需要的部分(僅BMP格式),和源碼一起放出來,希望對你有用,不夠用自己去改哈。
程式介面:
程式編譯環境:VS2005 VC++ MFC UNICODE
在程式的實現過程中,沒有去分析 BMP 的結構,而是直接調用了GDI+ Bitmap,我只是想使用,不想太多的深入。所以代碼閱讀起來很簡單,核心代碼就那麼2~3行。
這裡我假設讀者是第一次使用GDI+ 來進行逐步說明。如果你在這方面是姚明的手――高手@_@,請忽略。
1、包含GDI+ 的標頭檔和庫
我們需要包含 GDI+ 標頭檔,包含 lib,使用 Gdiplus 的別名。為了省事,我放到了 stdafx.h 裡。
//請在主架構裡GdiplusStartup / GdiplusShutdown#include //GDI+ 聲明,可以GDI/GDI+ 混合使用#pragma comment(lib, "gdiplus.lib")using namespace Gdiplus;
你也可以在 工程屬性->連結器->輸入->附加依賴項 裡包含 gdiplus.lib 檔案,也可以不使用別名,那麼定義GDI+ 對象的時候,就要帶上網域名稱,如 Gdiplus::Bitmap, 這裡建議還是 using namespace.
2、初始化和釋放GDI+ 調用
首先定義一個ULONG_PTR的成員變數 m_gdiplusToken ,這是一個DWORD資料類型,該成員變數用來儲存GDI+ 被初始化後在應用程式中的GDI+ 標識,以便能在應用程式退出後,引用該標識來調用Gdiplus:: GdiplusShutdown來關閉GDI+。細節請參考CBmp2MApp裡的相關代碼。
ULONG_PTR m_gdiplusToken; //GDI+
然後在 BOOL CBmp2MApp::InitInstance() 裡開始初始化 GDI+ 環境。
//初始化GID+GdiplusStartupInput gdiplusStartupInput;GdiplusStartup( &m_gdiplusToken,&gdiplusStartupInput,NULL );
最後,在int CBmp2MApp::ExitInstance()裡,我們來釋放GDI+ 的調用。注意:在嚮導產生的預設項目中,這個函數是沒有的,我們需要重載它。在類別檢視裡選擇CBmp2MApp,然後在屬性裡點重寫,就可以看到。(是不是太羅嗦了^_^)
int CBmp2MApp::ExitInstance() {//釋放GDI+ 調用GdiplusShutdown( m_gdiplusToken );return CWinApp::ExitInstance();}
3、圖片的分解
分解一張圖為多張,這是程式的預設模式。如源碼中的注釋,我只考慮了橫向分解,沒有考慮縱向的情況,也沒有考慮智能的擷取圖片的尺寸問題,預設就是16*16,如果你的圖片是32*32或其他的模式,請手動更改。但你點擊選擇檔案,成功選擇一個合適的圖片檔案之後,介面應該是所示的樣子。如果不想改變拆分圖片的儲存路徑,你可以直接點確定了,不出意外的話,會開啟一個檔案夾介面,然后里邊有N張儲存成功可供使用的圖片了。
核心函數就是下面的這個:
//分解,目前僅考慮 BMP 格式void CBmp2MDlg::ImageUnPack(LPCTSTR sPath,LPCTSTR sType,int x,int y){if( NULL==m_bitmap ) return; //must!//Bitmap *bmp = m_bitmap;int w = bmp->GetWidth();int h = bmp->GetHeight();CLSID clsid;GetEncoderClsid( sType,&clsid );CString ss;int i,k=1;for( i=0;i<w;i+=x,k++ ) //只考慮橫向{//建立指定大小的圖片Bitmap bt(x,y);//從它得到繪製裝置Graphics *gc = Graphics::FromImage( &bt );//從原圖片上截取指定大小的圖片貼到這個建立的圖片的上面gc->DrawImage( bmp,RectF(0,0,x,y),i,0,x,y,UnitPixel ); //ss.Format( _T("%s%s_%d.%s"),sPath,m_sFileTitle,k,GetType(sType) );//儲存到指定路徑bt.Save( ss,&clsid,NULL );//delete gc;gc = NULL;}ShellExecute( NULL,_T("open"),sPath,NULL,NULL,SW_SHOW );}
就是按照輸入的大小先建立一張空圖片,然後計算位置,從源圖片上的截取這個位置上的圖貼過來,然後儲存。
4、圖片的合并
合并多張圖為一張,就是上面的逆過程了。核心函數就是 ImagePack 請去參考源碼。
就是這麼個小工具,希望在你想用的時候能節省一點時間。你可以任意去擴充它,比如:增加圖片預覽的功能,儲存的命名規則,或者拖曳 ListCtrl 讓各圖片按你預想的順序排到一張大圖上……等等。