Visual C++作为一个功能非常强大的可视化应用程序开发工具,是
计算机界公认的最优秀的应用开发工具之一。Microsoft的基本类库MFC使得开发Windows应用程序比以往任何时候都要容易。C++提供的各种函数、指针操作和直接对硬件操作使得图像处理速度较快,专门为VC++
设计的OpenGL和DirectX技术可以使开发人员在Windows环境下比较容易地完成图像图形的高性能处理和显示。用VC++编制的应用软件无论在处理速度和图像的显示等方面都表现出较高的效率,因此在编制基于Windows的各类数字图像处理程序时, VC++无疑是
程序员进行图像处理的最佳选择。
本文主要介绍了本人在用VC++进行图像基本处理时获得一些技巧与经验,希望与广大爱好图像处理的编程者分享。
一、模板(template)的使用
对于图像处理应用
软件来说,图像数据的管理是至关重要的,在"电脑编程与技巧"杂志99年11期, 本人介绍了一个封装的通用图像基类(CImage),可完成BMP格式图像数据的管理和一些基本的图像处理功能。但是该CImage类只是对位图进行处理,即操作的数据类型为无符号8位字符型(BYTE)。但是在进行边缘检测、相关跟踪、快速傅立叶变换等图像处理中经常需要定义一些int或float类型的二维数组来保存处理的中间结果或最终结果。另外如果用OpenGL编程来进行图像处理和显示,为了保证跨平台特性,OpenGL定义了一套数据类型:有无符号8位字符型(BYTE)、16位短整型(short)、无符号16位短整型(unsigned short)、32位字符型(int)、无符号32位字符型(unsigned int)、单精度浮点数(float)等类型。如果对应于每一种数据类型都定义一个类,这样
虽然能解决
问题,但并不是一个明智的办法。例如要修改一个变量或函数,那对应于每一种数据类型定义的类多要做同样的修改,毫无疑问,这种方法操作繁琐,容易发生错误,需要做大量的拷贝修改
工作,因此是一种低效的方法。
C++引入的模板(template)概念,这一个关键字会告诉编译器下面的定义将操作一个或更多的非特定的类型。只有当对象被定义时,这些类型才必须被指定以使编译器能够替代它们。因此可以用一个非特定的参数来作类型名称,用该非特定的参数来定义一个通用的数据类或一个函数,诸如于MFC类库中的CArrary、CTypedPtrList等类。下面给出了支持不同数据类型的一个图像二维数据模板类和一个快速排序类。
1.定义不同数据类型的数据模板类
数据模板类的定义如下:
//--------不同数据类型图像二维数组模板的定义----------
template
class ImageTemplate
{
public:
T ** lp_AddRow; // 二维数组的数据指针
unsigned int Width; // 数组的宽度(列数)
unsigned int Height; // 数组的高度(行数)
unsigned int ImageSize; // 数组的大小
public:
ImageTemplate(void); // 构造函数
~ImageTemplate(void); // 析构函数
// 带参数的析构函数
ImageTemplate(unsigned int w, unsigned int h);
// 分配数据内存的函数
void Construct(unsigned int w, unsigned int h);
// 释放数据内存的函数
void DeleteData();
};
// 构造函数
template
ImageTemplate< T >::ImageTemplate(void)
{
lp_AddRow = NULL;
Width = Height = 0;
}
// 析构函数
template
ImageTemplate< T >::~ImageTemplate(void)
{
DeleteData();
}
// 带参数的析构函数
template
ImageTemplate< T >::ImageTemplate(unsigned int w, unsigned int h)
{
lp_AddRow = NULL;
Width = w;
Height = h;
ImageSize = w * h;
Construct(w, h);
}
// 分配数据内存的函数
template
void ImageTemplate< T >::Construct(unsigned int w, unsigned int h)
{
DeleteData();
if( Height > 0 ) lp_AddRow = new T*[Height];
if( ImageSize > 0 )
{
lp_AddRow[0] = new T[ImageSize];
memset(lp_AddRow[0], 0, ImageSize