由于这个库主要用于VC MFC下开发应用,因此目前可以下载到版本只支持MFC开发。如果您需要标准Win32的库,可以在回复时留下您的邮箱,或跟我联系。
Email:wuchunlei@163.com
QQ:819543772
EasyAnalysis图像分析库测试版以及源代码下载地址:
下载地址:
http://www.5941ts.com/EasyAnalysis/EasyAnalysis.rar
共190KB
本小节所涉及的源程序:
http://www.5941ts.com/EasyAnalysis/demo/4/TestDll.rar
从这节内容开始,我们正式开始涉及到EasyAnalysis图像分析库的应用当中,前面在Sobel处理图像的例子中我们用到了CBmp类,这个类是整个EasyAnalysis库中其它所有功能的基础,这一节主要讨论CBmp类以及它的基类CImage。
本章涉及到的源程序下载地址:
一.CImage和CBmp类的关系
CImage是一个抽象类,不能被实例化,其封装了很多不论是什么格式类型的图像文件都会用到的公共信息和操作,例如,打开文件、获取图像尺寸、类型以及获取图像像素等。而CBmp类继承自CImage类,该子类中封装了BMP文件所特有的信息和操作,比如按照BMP格式解析图像文件、存储图像文件获取文件头、信息头等特有操作。如果您需要继承出来自己的格式解析类,比如CJPG也应该从CImage继承,因为所谓图像处理类中都是以基类指针的形式接受图像数据,实现多态。
图中MemAssign类用来管理CImage中的指针操作。
二.重要结构体
1. BMP图像文件头:BITMAPFILEHEADER
BMP图像的文件头说明了BMP文件的基本信息,其声明如下:
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
其中,bfType为BMP标志,恒为0x424d,bfSize标志位图的实际长度。bfReserved1和bfReserved2为保留位无意义,bfOffBits标志像素数据所在的位置。对于采用CBmp导入的图像,可以通过GetBmpFileHeader()方法获取。
2. BMP图像信息头:BITMAPINFOHEADER
BMP图像的信息头说明了BMP文件的详细信息,声明如下:
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
biSize标志了该结构体大小,biWidth和biHeight分别标志了图像的宽高,biPlanes描述了目标设备位面个数,这里恒为1。biBitCount记录了图像的色彩位数,biCompression标志了图像的压缩方式,biSizeImage表示图像阵列的大小,biXPelsPerMeter和biYPelsPerMeter分别标志了目标设备水平和垂直的分辨率。biClrUsed表示图像中实际用到的颜色数。biClrImportant表示图像中相对重要的颜色数,为0时表示所有颜色一样重要。对于采用CBmp导入的图像,可以通过GetBmpInfoHeader()方法获取。
3. 调色板信息:RGBQUAD
如果图像颜色位数小于16的时候,BMP图像在文件头和信息头后面会紧跟一个调色板区域,调色板数量为2的颜色位数次方,例如8位BMP图像对应的调色板就为256个。图像像素区中数据实际保存的是调色板的索引,而不是实际的灰度值,实际的灰度值在调色板中表示。调色板结构体声明如下:
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
rgbReserved
4. 图像像素信息:IMAGEBITS
在EasyAnalysis中,无论图像颜色是2位还是24位,每个像素灰度都由RGB三个分量表示,而表示像素用的结构体就是IMAGEBITS,其声明形式如下:
{
BYTE c_R; //分别保存RGB分量
BYTE c_G;
BYTE c_B;
BYTE c_Flag; //保留位
};
很明显,
5. RGB2GRAY宏
该宏有三个参数R,G,B,分别对应某一像素RGB分量,这个宏的作用就是将RGB分量按照系数0.299,0.587,0.114转换为适合屏幕显示的灰度值。
三.CBmp的基本功能:
1. 打开图像文件:
函数声明:void CreateImage(LPCTSTR) throw()
返回值:void
函数功能:打开文件名为LPCTSTR所对应字符串的图像文件
{
CBmp m_Bmp;
m_Bmp.CreateImage("test.bmp");
}
catch(CPException &err)
{
int nErrCode=err.GetErrCode(); //取错误类型代码
MessageBox(err.GetErrMsg()); //弹出错误信息
}
异常描述:抛出CPException异常
I. 当传入的文件名为NULL的时候,异常提示信息为“文件名为NULL!”,一场代码为ERR_ALLOC_MEMORY
II. 当传入文件名长度为0的时候,异常提示信息为“文件名长度为0!"”异常代码为ERR_STRING_LENGTH_IS_ZERO
III. 另外由于该函数中用到CFileOpt类的Open方法,因此该类也会抛出Open中的异常,详细异常请参考上一节中关于Open的描述
2. 保存文件
函数声明:virtual void SaveData(LPCTSTR) throw()
返回值:void
函数功能:将当前图像保存到LPCTSTR指定的文件中,图像信息按照对象中信息头、文件头、调色板信息保存。
{
CBmp m_Bmp;
m_Bmp.CreateImage("test.bmp");
m_Bmp.SaveData(“Test1.bmp”);
}
catch(CPException &err)
{
int nErrCode=err.GetErrCode(); //取错误类型代码
MessageBox(err.GetErrMsg()); //弹出错误信息
}
注:文件头、信息头、调色板以及像素矩阵可以通过
3. 设置信息头:
函数声明:void SetBmpInfoHeader(BITMAPINFOHEADER ) throw();
返回值:void
函数功能:将参数中的信息头设置给对象
4. 设置文件头:
函数声明:void SetBmpFileHeader(BITMAPFILEHEADER ) throw();
返回值:void
函数功能:将参数中的文件头设置给对象
5. 设置调色板:
函数声明:void SetBmpQuad(RGBQUAD*,int) throw();
返回值:void
函数功能:设置调色板,参数中RGBQUAD *对应调色板序列指针的首地址,int为该序列的长度。
6. 设置像素数据:
函数声明:void SetBmpQuad(RGBQUAD*,int) throw();
返回值:void
函数功能:设置调色板,参数中RGBQUAD *对应调色板序列指针的首地址,int为该序列的长度。
7. 设置图像像素矩阵
函数声明:void SetBits(IMAGEBITS *pstBits,long ,long) throw();
返回值:void
函数功能:设置图像像素矩阵。第一个参数为像素矩阵中像素序列,第一个long为矩阵高,第二个参数为矩阵宽
应用举例:
I. 利用拷贝构造函数复制对象
CBmp m_NewBmp;
try
{
//通过文件初始化CBmp对象
m_Bmp.CreateImage("test.bmp");
m_NewBmp=m_Bmp; //复制图像
m_NewBmp.SaveData("c:\Test.bmp");
}
catch(CPException &err)
{
int nErrCode=err.GetErrCode(); //取错误类型代码
MessageBox(err.GetErrMsg()); //弹出错误信息
}
II.
{
CBmp m_Bmp;
CBmp m_NewBmp;
//通过文件初始化CBmp对象
m_Bmp.CreateImage("test.bmp");
m_NewBmp.SetBmpFileHeader(m_Bmp.GetBmpFileHeader());
m_NewBmp.SetBmpInfoHeader(m_Bmp.GetBmpInfoHeader());
m_NewBmp.SetBmpQuad(m_Bmp.GetBmpQuad(),pow(2, m_Bmp.GetBitCount()));
m_NewBmp.SetBits(m_Bmp.GetBits(),m_Bmp.GetHeight(),m_Bmp.GetWidth());
m_NewBmp.SaveData("c:\Test.bmp");
}
catch(CPException &err)
{
int nErrCode=err.GetErrCode(); //取错误类型代码
MessageBox(err.GetErrMsg()); //弹出错误信息
}
m_Bmp.GetBmpFileHeader(),,m_Bmp.GetBmpInfoHeader(),m_Bmp.GetBmpQuad(),m_Bmp.GetBitCount(),m_Bmp.GetBits(),m_Bmp.GetHeight(),m_Bmp.GetWidth()分别为取文件头、信息头、调色板、颜色位数、像素矩阵,图像高,图像宽。
pow(2, m_Bmp.GetBitCount())用于根据位数位数计算颜色数,例如颜色位数为8,则颜色数为pow(2,8)=256
8. 设置指定点的像素值
函数声明:void SetBitXY(long ,long,IMAGEBITS) throw();
返回值:void
函数功能: 将IMAGEBITS对应的像素值插入像素矩阵(long,long)位置
9. 获取图像高度
函数声明:long GetHeight() throw();
返回值:long,返回图像的高度
函数功能:返回图像高度
异常说明:如果文件未打开跑出CPException异常。
10.获取图像宽度
函数声明:long GetWidth() throw();
返回值:long,返回图像的宽度
函数功能:返回图像宽度
异常说明:如果文件未打开跑出CPException异常。
11.获取图像颜色位数
函数声明:int GetBitCount() throw();
返回值:int 返回图像颜色位数
函数功能:获取图像颜色位数
异常说明:如果文件未打开跑出CPException异常。
应用举例:
{
//取图像宽高和位数
char psMsg[256]={0};
sprintf(psMsg,"nHeight=%d,nWidth=%d,BitCount=%d",m_Bmp.GetHeight(),
m_Bmp.GetWidth(),m_Bmp.GetBitCount());
MessageBox(psMsg);
}
catch(CPException &err)
{
int nErrCode=err.GetErrCode(); //取错误类型代码
MessageBox(err.GetErrMsg()); //弹出错误信息
}
12.获取图像文件头:
函数声明:BITMAPFILEHEADER GetBmpFileHeader() throw()
返回值:BITMAPFILEHEADER
函数功能:获取图像信息头结构体
13.获取图像信息头:
函数声明:BITMAPINFOHEADER GetBmpInfoHeader() throw()
返回值:BITMAPINFOHEADER
函数功能:获取图像信息头结构体
13.取调色板
函数声明:RGBQUAD *GetBmpQuad() throw();
返回值:RGBQUAD
函数功能:获取图像的调色板
注:该函数不会返回调色板数量,因此需要GetBitCount()获得调色板数量,两者需要配合使用。
14.取像素矩阵
函数声明:IMAGEBITS *GetBits() throw();
返回值:IMAGEBITS 数组指针
函数功能:获取图像的调色板
应用举例:
注:
{
CBmp m_Bmp;
IMAGEBITS *pstBits=NULL; //用于保存像素矩阵
m_Bmp.CreateImage("test.bmp"); //通过文件初始化CBmp对象
pstBits=new IMAGEBITS[m_Bmp.GetHeight()*m_Bmp.GetWidth()]; //分配空间
memcpy(pstBits,m_Bmp.GetBits(),m_Bmp.GetHeight()*m_Bmp.GetWidth()); //复制内存
delete [] pstBits; //销毁空间
}
catch(CPException &err)
{
int nErrCode=err.GetErrCode(); //取错误类型代码
MessageBox(err.GetErrMsg()); //弹出错误信息
}
I. 返回的指针不能用Delete销毁,在对象析构的时候该指针会自动销毁。如果需要在对象析构以后继续使用该指针请使用Memcpy拷贝该指针
II. 该函数不会返回像素矩阵的尺寸,因此需要与GetHeight(),GetWidth()配置使用。
15.取指定点的像素值
函数声明:IMAGEBITS GetBitXY(long ,long) throw();
返回值:IMAGEBITS ,某一点的像素值
函数功能: 取(long,long)位置的像素值