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基本可以支持所有的主流格式,其支持的文件格式有十几种之多。真是个好东西啊!
原文地址:http://blog.csdn.net/summersolstice/article/details/5148258