使用FreeImage写通用图像加载器

FreeImage库支持多种类型图像的特性让我有一种想法,写一个通用图像加载显示器,由于又刚好在学习MFC,于是也就抱着写着玩的心态开始了,FreeImage可以很轻松的加载各种格式的图像,但是显示这些图像又让我犯难了。MFC庞大的框架确实很头疼,但是一旦你明确目标是什么,框架也就不成其为问题。所有的主体代码都是在视类完成的。

注意:使用FreeImage库前,须将FreeImage动态库FreeImage.dll,FreeImage.lib和头文件FreeImage.h放在工程目录下,并将FreeImage.lib添加到工程中,可在工程中使用#pragma commet(lib,"FreeImage.lib"宏,或直接在Project->Settings->Link选项中添加。比添加头文件FreeImage.h在相应的地方。

第一步:通用图像加载;

通用图像的加载函数:FIBITMAP* GenericLoader(const char *ptrFileName)

FIBITMAP* CGenericPictureReaderView::GenericLoader(const char *ptrFileName) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; fif = FreeImage_GetFileType(ptrFileName); if(fif == FIF_UNKNOWN) { fif = FreeImage_GetFIFFromFilename(ptrFileName); } if(fif != FIF_UNKNOWN && FreeImage_FIFSupportsReading(fif)) { FIBITMAP* dib = FreeImage_Load(fif,ptrFileName,0); return dib; } return NULL; }  

第二步:设置菜单栏的打开操作的消息响应函数;

其代码如下:

 void CGenericPictureReaderView::OnFileOpen() { // TODO: Add your command handler code here // TODO: Add your command handler code here CFileDialog fileDlg(TRUE,NULL,"*.*",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "all(*.*)|*.*|bmp(*.bmp)|*.bmp|/ jpg(*.jpg)|*.jpg|png(*.png)|*.png|/ tif(*.tif)|*.tif|gif(*.gif)|*.gif|/ psd(*.psd)|*.psd|pgm(*.pgm)|*pgm||", NULL); RECT rt; GetClientRect(&rt); if(IDOK == fileDlg.DoModal()) { strFileName = fileDlg.GetPathName(); // SetWindowText(strFileName); AfxGetMainWnd()->SetWindowText(strFileName); InvalidateRect(&rt); } }

第三步:显示图像

图像分为两种类型,第一种:没有调色板的图像,直接使用StretchDIBit函数绘制。第二种:使用调色板,先载入调色板,然后使用StretchDIBit函数绘制。

有调色板的图像,先要创建调色板,下面就是根据FIBITMAP创建调色板的函数:

HPALETTE CGenericPictureReaderView::GetPalette(FIBITMAP *dib) { struct { WORD Version; WORD NumberOfEntries; PALETTEENTRY palPalEntry[256]; } palette = {0x300,256}; RGBQUAD* ptrRGBTable = FreeImage_GetPalette(dib); UINT nClrUsed = FreeImage_GetColorsUsed(dib); for(UINT i=0;i<nClrUsed;i++) { palette.palPalEntry[i].peBlue = ptrRGBTable[i].rgbBlue; palette.palPalEntry[i].peGreen = ptrRGBTable[i].rgbGreen; palette.palPalEntry[i].peRed = ptrRGBTable[i].rgbRed; palette.palPalEntry[i].peFlags = 0; } HPALETTE Palette = CreatePalette((LPLOGPALETTE)&palette); return Palette; }

在OnDraw函数中进行绘制操作:

void CGenericPictureReaderView::OnDraw(CDC* pDC) { CGenericPictureReaderDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here FIBITMAP* dib = GenericLoader(strFileName); int width = FreeImage_GetWidth(dib); int height = FreeImage_GetHeight(dib); BITMAPINFO* pBitmapInfo = FreeImage_GetInfo(dib); BYTE* pImgData = FreeImage_GetBits(dib); RGBQUAD* pPalette = FreeImage_GetPalette(dib); if(pPalette) { HPALETTE Pal = GetPalette(dib); HPALETTE oldPal = ::SelectPalette(pDC->GetSafeHdc(),Pal,TRUE); ::RealizePalette(pDC->GetSafeHdc()); ::StretchDIBits(pDC->GetSafeHdc(),0,0,width,height,0,0,width,height, (const void*)pImgData,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); ::SelectPalette(pDC->GetSafeHdc(),oldPal,TRUE); ::DeleteObject((HGLOBAL)Pal); } else { ::StretchDIBits(pDC->m_hDC,0,0,width,height,0,0,width,height, (const void*)pImgData,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); } FreeImage_Unload(dib); }

当需要发行你的程序时,需要将动态链接库FreeImage.dll一起打包发行。

使用FreeImage大大减轻了图像载入的工作,如果全得自己写,想想后果吧!那么多图像格式,你不得不自己设计自己的图像类,工作量是极其反复的。据称,FreeImage基本可以支持所有的主流格式,其支持的文件格式有十几种之多。真是个好东西啊!

 使用FreeImage写通用图像加载器_第1张图片

你可能感兴趣的:(框架,工作,command,null,mfc,colors)