FreeImage使用方法
一,、FreeImage 簡介 FreeImage 是一款免費的、開源的,、跨平臺(Windows ,、Linux 和Mac OS X )的,支持20 多種圖像類型的(如BMP ,、JPEG ,、GIF 、PNG ,、TIFF 等)圖像處理庫,。其最大優(yōu)點就是采用插件驅(qū)動型架構(gòu),具有快速,、靈活、簡單易用的特點,,得到了廣泛使用,。相關(guān)的源碼、庫文件及幫助文檔可以從http://freeimage./ 免費下載使用,。下載最新的FreeImage 3.14.1 [WIN32], 解壓縮該FreeImage3141Win32.zip文件,,包含FreeImage.h、FreeImage.lib和 FreeImage.dll 文件,。 FreeImage 的主要功能有多格式位圖的讀寫,;方便的位圖信息獲取,;位深度轉(zhuǎn)換,;位圖頁面訪問;基本的幾何變換和點處理,;通道合并與混合等,。FreeImage 暫時不支持矢量圖形和高級圖像處理,位圖繪制需要由用戶來完成,。 FreeImage 中的所有函數(shù)都以FreeImage_ 開頭,,如圖像文件的讀寫函數(shù)分別為FreeImage_Load 和FreeImage_Save 。FIBITMAP 數(shù)據(jù)結(jié)構(gòu)保存著位圖信息和像素數(shù)據(jù),,是FreeImage 的核心,。
二、初始化 FreeImage FreeImage 主要包含頭文件FreeImage.h ,、靜態(tài)鏈接庫FreeImage.lib ,、FreeImaged.lib ,動態(tài)鏈接庫FreeImage.dll 和FreeImaged.dll ,。其中,,以d 結(jié)尾的庫文件用于調(diào)試版,,其余用于發(fā)行版。為了在VC 中使用FreeImage方法如下: #i nclude"FreeImage.h" #ifdef _DEBUG #pragma comment(lib, "FreeImaged.lib") #else #pragma comment(lib, "FreeImage.lib") #endif 默認情況下,,FreeImage 被當作動態(tài)鏈接庫,。若需用作靜態(tài)鏈接庫,則在應(yīng)用程序類的InitInstance 中調(diào)用FreeImage_Initialise(0) 加載FreeImage 庫,,重載ExitInstance 并在其中調(diào)用FreeImage_DeInitialise() 釋放FreeImage 庫,。 三、讀取圖像 FreeImage 是插件驅(qū)動的,,每種位圖的讀寫函數(shù)實際上就是一個插件模塊,。采用插件驅(qū)動型構(gòu)架便于功能擴展,通過創(chuàng)建或引入新的插件,,可以支持新的圖像類型,。為便于維護打開的位圖,在文檔類添加FIBITMAP 型指針m_pFI ,,用以指向打開的位圖,。在構(gòu)造函數(shù)中將其置為空,在析構(gòu)函數(shù)中調(diào)用FreeDIB 將其釋放,。FreeDIB 定義如下:
void CDIPDoc:: FreeDIB () { if(m_pFI) { FreeImage_Unload(m_pFI);// 釋放位圖 m_pFI = NULL; } }
在OnNewDocument() 和OnFileOpen() 函數(shù)中也應(yīng)調(diào)用FreeDIB ,,以確保建立或打開新圖像時先釋放以前的位圖。
讀取圖像的基本步驟如下:
調(diào)用庫函數(shù)FreeImage_GetFileType 由文件頭分析文件類型,,若不能識別,,則調(diào)用庫函數(shù)FreeImage_GetFIFFromFilename 從文件擴展名判斷文件類型。
若是支持的圖像文件類型,,則調(diào)用庫函數(shù)FreeImage_FIFSupportsReading 判斷是否支持該位圖類型的讀操作,,若支持則調(diào)用庫函數(shù)FreeImage_Load 加載位圖。
在文檔類中添加成員函數(shù)LoadDIB ,,實現(xiàn)位圖讀入功能,,代碼如下:
FIBITMAP* CDIPDoc::LoadDIB(LPCTSTR lpszPathName, int flag){
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
fif = FreeImage_GetFileType(lpszPathName);
if(fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(lpszPathName); if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
return dib;
}
return NULL;
}
在文檔類中重載OnFileOpen ,調(diào)用GetFilterString 創(chuàng)建文件類型過濾字符串,,調(diào)用LoadDIB 加載位圖,。
void CDIPDoc::OnFileOpen()
{
FIBITMAP* pFI = NULL;
char szFilter[2048];
GetFilterString(szFilter);
CFileDialog dlg(TRUE,NULL,NULL,
OFN_HIDEREADONLY, szFilter);
if(dlg.DoModal() == IDOK) {
CString strPath = dlg.GetPathName();
pFI = LoadDIB(strPath, 0);
if(pFI) {
FreeDIB();// 釋放以前的位圖
m_pFI = pFI;// 指向新位圖
UpdateAllViews (NULL);
}
}
}
四、顯示圖像 在視圖類的OnDraw 函數(shù)中繪制圖像,。當前源圖像與客戶區(qū)尺寸相同時,,調(diào)用SetDIBitsToDevice 繪制,這樣可以加快繪制速度,,否則調(diào)用StretchDIBits 按比例縮放位圖,。
void CDIPView::OnDraw(CDC* pDC)
{
CDIPDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
FIBITMAP *pFI = pDoc->m_pFI;
if(pFI) {
BYTE* pBits = FreeImage_GetBits(pFI);
BITMAPINFO* pIf=FreeImage_GetInfo(pFI);
int W = FreeImage_GetWidth(pFI);
int H = FreeImage_GetHeight(pFI);
CRect rectClient;GetClientRect(rectClient);
int dstW = rectClient.Width();
int dstH = rectClient.Height();
::SetStretchBltMode(pDC->GetSafeHdc(),COLORONCOLOR);
if(dstW == W && dstH == H) {
::SetDIBitsToDevice(pDC->GetSafeHdc(),0,0, W, H,0,0,0, H,pBits,pIf,DIB_RGB_COLORS);
}
else {// 按比例縮放
float fScale=(float)(W*dstH)/(float)(H*dstW);
if(fScale > 1.0f)
dstH = (int) (dstH / fScale);
else
dstW = (int) (dstW * fScale);
::StretchDIBits(pDC->GetSafeHdc(),0,0,dstW,dstH,0,0,W,H,pBits,pIf,DIB_RGB_COLORS,SRCCOPY);
}
}
}
五、保存圖像 (1 )調(diào)用FreeImage_GetFIFFromFilename 函數(shù)從文件名判斷期望保存的圖像類型,如果不支持則返回,;否則轉(zhuǎn)(2 ),。
(2 )調(diào)用FreeImage_GetImageType 判斷當前位圖數(shù)據(jù)類型,若為標準位圖,,則測試是否支持該種圖像類型的寫操作以及位深度轉(zhuǎn)換,,否則調(diào)用FreeImage_FIFSupportsExportType 檢查是否能夠輸出當前位圖。若測試成功,,則調(diào)用FreeImage_Save 保存位圖,。
在文檔類中定義成員函數(shù)SaveDIB 實現(xiàn)上述功能,代碼如下:
BOOL CDIPDOC::SaveDIB(FIBITMAP *dib, LPCTSTR *lpszPath, int flag){
FREE_IMAGE_FORMAT fif =FIF_UNKNOWN;
BOOL bSuccess = FALSE;
fif=FreeImage_GetFIFFromFilename(lpszPath);
if(fif != FIF_UNKNOWN ) {
BOOL bCanSave;
FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
if(image_type == FIT_BITMAP) {
WORD bpp = FreeImage_GetBPP(dib);
bCanSave=(FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp));
}
else {
bCanSave=FreeImage_FIFSupportsExportType(fif, image_type);
}
if(bCanSave) bSuccess=
FreeImage_Save(fif,dib,lpszPath,flag);
}
return bSuccess;
}
六,、一個簡單的程序?qū)嵗?/FONT> #i nclude <iostream> #i nclude <cassert> #i nclude"FreeImage.h" #pragma comment(lib,"FreeImage.lib")
#define show(a) std::cout<< a <<std::endl
int main(int argc,char *argv) { //初始化FreeImage FreeImage_Initialise(TRUE);
//默認分配一塊內(nèi)存存儲影像,,其中bpp表示圖像深度 //FIBITMAP *bitmap = FreeImage_AllocateT(FIT_BITMAP,Width,height,bpp, //red_mask,green_mask,blue_mask);
//最后一個參數(shù)用來改變函數(shù)的行為或激活位圖插件的一種特性,每個插件有他自己的參數(shù)集 //FreeImage_LoadU參數(shù)都是一樣,,不過只在win32下起作用 FIBITMAP * bmp = FreeImage_Load(FIF_BMP,"cs5.BMP",BMP_DEFAULT);
//FreeImage_SaveU和上面的一樣 if( bmp) { //FreeImage_Save(FIF_BMP, bmp, "whtm.bmp", BMP_DEFAULT); }
//獲取影像的寬高,,都以像素為單位 int Width = FreeImage_GetWidth(bmp); int Height = FreeImage_GetHeight(bmp);
//獲取影像的byte寬度,不對,,我上面運行與Width相等 int ByteWidth = FreeImage_GetLine(bmp);
//返回每個像素使用灰度值 show(FreeImage_GetBPP(bmp)); //返回數(shù)據(jù)類型 show(FreeImage_GetImageType(bmp)); //返回調(diào)色板的大小 show(FreeImage_GetColorsUsed(bmp));
show(Width<<" "<<Height<<" "<<ByteWidth);
//assert(ByteWidth == Width*8 );
show(FreeImage_GetDIBSize(bmp));
//有調(diào)用load就有unload,,否則就會內(nèi)存泄漏 FreeImage_Unload(bmp); FreeImage_DeInitialise();
return 0; } 轉(zhuǎn)載于梅園 《FreeImage學(xué)習筆記》 http://blog./u1/58776/showart_527523.html
參考資料: FreeImage圖形庫說明文檔(中文版):http://download.csdn.net/source/2756601 |
|