FreeImage的图像处理软件
(来源:http://www.comprg.com.cn/detail.asp?hw_id=7843 )
一、引言
图 像处理与分析软件都涉及到图像文件的读写与绘制,以及位图信息的获取与设置等基本操作,需要编写相应的函数来实现这些功能。然而,图像文件类型的多样性以 及文件格式的复杂性,导致图像读写函数的实现费时费力,且易出错。事实上,没有必要去重复这些基础工作。相反,可以借助于现有的图像处理库,如 FreeImage 、 ImageLoad 、 CImage 、 ImageJ 、 IPL 等来实现这些基本功能,简化图像处理与分析软件的开发工作,从而把更多的精力放在更高级、面向具体问题的图像处理与分析算法的设计上,以提高开发效率。本文将以单文档应用程序为例,简要介绍利用 Visual C++ 6.0 下开发基于 FreeImage 的图像处理软件的基本方法。
二、 FreeImage 简介
FreeImage 是一款免费的、开源的、跨平台(Windows 、Linux 和Mac OS X )的,支持20 多种图像类型的(如BMP 、JPEG 、GIF 、PNG 、TIFF 等)图像处理库。其最大优点就是采用插件驱动型架构,具有快速、灵活、简单易用的特点,得到了广泛使用。相关的源码、库文件及帮助文档可以从http://freeimage.sourceforge.net/ 免费下载使用。
FreeImage 的主要功能有多格式位图的读写;方便的位图信息获取;位深度转换;位图页面访问;基本的几何变换和点处理;通道合并与混合等。FreeImage 暂时不支持矢量图形和高级图像处理,位图绘制需要由用户来完成。
FreeImage 中的所有函数都以FreeImage_ 开头,如图像文件的读写函数分别为FreeImage_Load 和FreeImage_Save 。FIBITMAP 数据结构保存着位图信息和像素数据,是FreeImage 的核心。
三、初始化 FreeImage
FreeImage 主要包含头文件FreeImage.h 、静态链接库FreeImage.lib 、FreeImaged.lib ,动态链接库FreeImage.dll 和FreeImaged.dll 。其中,以d 结尾的库文件用于调试版,其余用于发行版。为了在VC 中使用FreeImage ,需要将上述文件复制到相应目录下。将FreeImage.h 复制到VC98/Include/ 中,FreeImaged.lib 和FreeImage.lib 复制到VC98/Lib/ 中,FreeImaged.dll 和FreeImage.dll 复制到system32 目录下。
建立一个单文档应用程序DIP ,在工程的stdafx.h 文件中包含FreeImage.h ,并在工程设置对话框的Link 标签中分别为调试版和发行版添加FreeImaged.lib 和FreeImage.lib 。也可以在stdafx.h 中自动链接FreeImage 库,代码如下:
#ifdef _DEBUG
#pragma comment(lib, "FreeImaged.lib")
#else
#pragma comment(lib, "FreeImage.lib")
#endif
默认情况下,FreeImage 被当作动态链接库。若需用作静态链接库,则在应用程序类的InitInstance 中调用FreeImage_Initialise(0) 加载FreeImage 库,重载ExitInstance 并在其中调用FreeImage_DeInitialise() 释放FreeImage 库。
四、读取图像
FreeImage 是插件驱动的,每种位图的读写函数实际上就是一个插件模块。采用插件驱动型构架便于功能扩展,通过创建或引入新的插件,可以支持新的图像类型。
为便于维护打开的位图,在文档类添加FIBITMAP 型指针m_pFI ,用以指向打开的位图。在构造函数中将其置为空,在析构函数中调用FreeDIB 将其释放。FreeDIB 定义如下:
void CDIPDoc:: FreeDIB ()
{
if(m_pFI) {
FreeImage_Unload(m_pFI);// 释放位图
m_pFI = NULL;
}
}
在OnNewDocument() 和OnFileOpen() 函数中也应调用FreeDIB ,以确保建立或打开新图像时先释放以前的位图。
读取图像的基本步骤如下:
调用库函数FreeImage_GetFileType 由文件头分析文件类型,若不能识别,则调用库函数FreeImage_GetFIFFromFilename 从文件扩展名判断文件类型。
若是支持的图像文件类型,则调用库函数FreeImage_FIFSupportsReading 判断是否支持该位图类型的读操作,若支持则调用库函数FreeImage_Load 加载位图。
在文档类中添加成员函数LoadDIB ,实现位图读入功能,代码如下:
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;
}
若想在打开文件对话框中显示FreeImage 所支持的图像文件类型,则可以在文档类中添加GetFilterString 函数,用以创建FreeImage 支持的图像类型过滤字符串。其基本过程为:调用FreeImage_GetFIFCount 函数获取FreeImage 库所支持的图像文件类型数;针对每种图像类型,调用FreeImage_GetFIFExtensionList 获取其扩展名列表,调用FreeImage_GetFIFDescription 函数获取其类型描述字符串;将各种图像类型信息依次连接成“BMP Files (bmp)|*.bmp|JPEG Files (jpg,jif,jpeg,jpe)|*.jpg;*.jif;*.jpeg;*.jpe|| ”形式的字符串,就形成了图像文件类型过滤字符串。
int CDIPDoc::GetFilterString(char *szFilter)
{
int i, iCount;
char Filter[1024], *token;
Filter[0] = '/0'; szFilter[0] = '/0';// 空字符
for(i=0; i<FreeImage_GetFIFCount();i++){
strcat(Filter,FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i));
strcat(Filter, ",");
}
Filter[strlen(Filter)-1] = '/0';
strcat(szFilter, "All image files|");
token = strtok(Filter, ",");
while(token != NULL) {
strcat(szFilter, "*."); strcat(szFilter, token);
strcat(szFilter, ";");token = strtok(NULL, ",");
}
szFilter[strlen(szFilter)-1] = '|';
Filter[0] = '/0'; iCount = 0;
for(i=0;i<FreeImage_GetFIFCount();i++){
sprintf(Filter, "%s (%s)|", FreeImage_GetFIFDescription((FREE_IMAGE_FORMAT)i),FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i));
strcat(szFilter, Filter);
strcpy(Filter,FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i));
token = strtok(Filter, ",");
while(token != NULL) {
strcat(szFilter, "*.");strcat(szFilter, token);
strcat(szFilter, ";");token=strtok(NULL, ",");
}
szFilter[strlen(szFilter)-1] = '|'; iCount++;
}
strcat(szFilter, "All Files (*.*)|*.*|");
strcat(szFilter, "|");
return iCount;
}
在文档类中重载OnFileOpen ,调用GetFilterString 创建文件类型过滤字符串,调用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 函数中绘制图像。当前源图像与客户区尺寸相同时,调用SetDIBitsToDevice 绘制,这样可以加快绘制速度,否则调用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 )调用FreeImage_GetFIFFromFilename 函数从文件名判断期望保存的图像类型,如果不支持则返回;否则转(2 )。
(2 )调用FreeImage_GetImageType 判断当前位图数据类型,若为标准位图,则测试是否支持该种图像类型的写操作以及位深度转换,否则调用FreeImage_FIFSupportsExportType 检查是否能够输出当前位图。若测试成功,则调用FreeImage_Save 保存位图。
在文档类中定义成员函数SaveDIB 实现上述功能,代码如下:
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;
}
在文档类中重载OnFileSaveAs ,调用GetFilterString 创建文件类型过滤字符串,调用SaveDIB 按指定格式保存位图,代码如下。
void CDIPDoc::OnFileSaveAs()
{
char szFilter[2048];
int nFileFormats = 0;
nFileFormats = GetFilterString(szFilter);
CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,szFilter);
if(dlg.DoModal() == IDOK) {
CString strPathName, strExtList;
int nPos = 0, nFilterIndex;
nFilterIndex = dlg.m_ofn.nFilterIndex;
strPathName = dlg.GetPathName();
if(nFilterIndex > 1 && nFilterIndex <= FreeImage_GetFIFCount()){
strExtList = FreeImage_GetFIFExtensionList(
(FREE_IMAGE_FORMAT)(nFilterIndex-2));
nPos = strExtList.Find(',');
if(nPos == -1)
strPathName += "."+strExtList;
else
strPathName += "."+strExtList.Left(nPos);
}
SaveDIB(m_pFI, strPathName);
}
}
七、结语
FreeImage 是一款简单易用,能够读写多种图像类型,以及图像类型之间的相互转换和位深度转换,其位图信息和位图数据由FIBITMAP 数据结构维护,可以在此基础上实现高级的图像处理与分析算法,提高了软件开发效率。
FreeImage的图像处理软件相关推荐
- 收集的网络上大型的开源图像处理软件代码(提供下载链接)
要写好一个图像处理软件,仅靠自己看书是完全不够的,要多方面学习,借鉴前人的经验,要集思广益.多面出击.如今网络发达,图像学的资料其实也到处都是.只是往往个人能力或精力有限,在短时间内无法找到那些也许藏 ...
- 开源图像处理软件代码
1. 最著名的开源图像软件:GIMP. 开发语言:C GIMP号称Linux下的PhotoShop,总观其工程,确实达到了PhotoShop早期版本的功能.三大利器:选区.图层.蒙板一应俱全,滤镜也非 ...
- 图像处理 区域删除_FotoWorks XL( 图像处理软件 )中文版分享
FotoWorks XL 2020是一款来自国外所推出的图像处理软件,该软件功能非常实用,这款软件可以让用户完成次次专业的图片编辑,不仅如此,相对于其他同类软件而言,这款软件具备了非常简洁的操作界面, ...
- 3D图形图像处理软件HOOPS介绍及下载
HOOPS 3D Application Framework(以下简称HOOPS)是建立在OpenGL.Direct3D等图形编程接口之上的更高级别的应用程序框架.不仅为您提供强大的图形功能,还内嵌了 ...
- ae 创建图像等高线 蒙版_Pixelmator ——图像处理软件
Mac图像处理软件哪个好用?Pixelmator Pro Mac汉化版是一款专业的图像处理软件,干净整洁的界面易于操作,支持常见的psD.TIFF.JPEG.PNG.PDF.Eps 等图形文件格式,以 ...
- ImageJ Nikon_科研人必备图像处理软件—ImageJ软件分享
文 / 利刃君 微信ID / ziyuanliren666 全文共1483字,推荐阅读时间4分钟. 没有不好的数据,只有不好的分析.作为一名科研人人员,每天面对各种让人抓狂的实验数据.图像,拥有一款功 ...
- FreeType, FFmpeg, SDL, 图像处理软件, Mac OS X, Objective-C
http://antkillerfarm.github.io/ FreeType使用指南 FreeType是一套跨平台的字体文件编程开发包.它的官网是www.freetype.org,你可以到这个网站 ...
- tensorflow2.0 图像处理项目_航天泰坦丨国产自主遥感图像处理软件当自强
点击蓝字关注 国产自主遥感图像处理软件当自强 航天泰坦公司超算平台产品 通过浙江省自然资源监测中心验收 近日,航天泰坦公司自主研发的泰坦超算平台产品在浙江省信息化测绘创新基地通过了浙江省自然资源监测中 ...
- opencv对图像是软解码_基于opencv和c++的图像处理软件设计与实现(26页)-原创力文档...
毕业设计中文摘要 基于opencv和c++的图像处理软件设计与实现 摘要: 本文主要对基于opencv和c++的图像处理软件设计与实现进行介绍.本软件由主界面和若干二级菜单组成,主界面功能有文件操作. ...
最新文章
- POJ - 2763 Housewife Wind LCA+dfs序+线段树
- 《3D数学基础》1.8 混合积
- 三分钟学会css3中的flexbox布局
- python基础语法手册format-python基础_格式化输出(%用法和format用法)
- 006_Curator框架一
- Unity3D学习笔记之九为场景添加细节(二)
- MySQL——binlog,redo log
- STM32F103_ADC-DMA通道采集
- 页面的主题标记--body
- Cmd Markdown编辑器简明语法手册
- golang github.com/go-sql-driver/mysql 遇到的数据库,设置库设计不合理的解决方法
- 第二章、使用变量、操作符和表达式
- sql事务Transaction
- Server 安装 caffee
- SqlServer数据库导入 mdf,ldf,ndf 格式文件操作
- 新买的华为Matebook,Office没激活,激活方法在这里!!!
- 解决网页版权符号模糊不清
- Android系统屏幕亮度调节Brightness
- 机器学习笔记(六)-神经网络:概述
- 手游联运新增开放平台!
热门文章
- 【python】双向冒泡排序
- 卡巴斯基CEO称勒索病毒为最严重的网络攻击之一
- 冒险岛私人服务器详细架设教程
- 上拉、下拉以及对应上拉电阻和下拉电阻的作用原理
- python加减_python实现输入数字的连续加减方法
- Java stream流式计算详解
- 论文学习-Exploiting Long-Term Dependencies for Generating Dynamic Scene GraphsExploiting Long-Term Depe
- u盘安装浪潮服务器_安装linux操作系统--浪潮服务器
- C# HTTP Basic 认证
- 约束布局 ConstraintLayout 的使用