从cvLoadImage开始--OpenCV源码阅读之三[转]

cvSaveImage/cvLoadImage函数用于保存和读取图像,两者的结构基本相似。
下面我们主要分析cvSaveImage函数的实现。

cvLoadImage函数位于"OpenCV/otherlibs/highgui/loadsave.cpp"文件:

CV_IMPL IplImage*
cvLoadImage( const char* filename, int iscolor )
{
return (IplImage*)icvLoadImage( filename, iscolor, false );
}

内部基于icvLoadImage函数实现。其中icvLoadImage函数的第三个参数可以
用于装载矩阵,这里被忽略(false表示读图像)。

icvLoadImage函数的主要部分如下


static void*
icvLoadImage( const char* filename, int flags, bool )
{
// 查找图像的读驱动

GrFmtReader* reader = g_Filters.FindReader( filename );

// 利用图像读驱动读出图像头信息(高宽等属性)

reader->ReadHeader();

// 高度/宽度

size.width = reader->GetWidth();
size.height = reader->GetHeight();

// 是否彩色

int iscolor = reader->IsColor();

// 彩色通道数为3,灰度为1

int cn = iscolor ? 3 : 1;

// 创建影像

IplImage* image = cvCreateImage( size, type, cn );

// 利用读驱动读图像的所有像素
// image->data.ptr对应数据的开始地址
// image->step表示每行像素所在内存的大小

reader->ReadData( image->data.ptr, image->step, iscolor );

return image;
}

 

其中g_Filters是一个静态变量:

// global image I/O filters
static CvImageFilters g_Filters;

CvImageFilters::CvImageFilters()
{
m_factories = new GrFmtFactoriesList;

m_factories->AddFactory( new GrFmtBmp() );
m_factories->AddFactory( new GrFmtJpeg() );
m_factories->AddFactory( new GrFmtSunRaster() );
m_factories->AddFactory( new GrFmtPxM() );
m_factories->AddFactory( new GrFmtTiff() );

...
}

GrFmtFactoriesList在grfmt_base.h/grfmt_base.cpp中定义,用于保存GrFmtFilterFactory
对象指针的链表。GrFmtFilterFactory为各种格式图像读写驱动的构造工厂基类:

class GrFmtFilterFactory
{
public:

GrFmtFilterFactory();
virtual ~GrFmtFilterFactory() {};

const char* GetDescription() { return m_description; };
int GetSignatureLength() { return m_sign_len; };
virtual bool CheckSignature( const char* signature );
virtual bool CheckExtension( const char* filename );
virtual GrFmtReader* NewReader( const char* filename ) = 0;
virtual GrFmtWriter* NewWriter( const char* filename ) = 0;

protected:
const char* m_description;
// graphic format description in form:
// <Some textual description>( *.<extension1> [; *.<extension2> ...]).
// the textual description can not contain symbols '(', ')'
// and may be, some others. It is safe to use letters, digits and spaces only.
// e.g. "Targa (*.tga)",
// or "Portable Graphic Format (*.pbm;*.pgm;*.ppm)"

int m_sign_len; // length of the signature of the format
const char* m_signature; // signature of the format
};

其中GetDescription()用于获取图像文件名的描述,类似于"文本文件 (*.txt)"格式。

GetSignatureLength()用于获取图像文件的标志大小。对于tiff格式,开头有一个"II"或者是"MM"的标志,长度为2。
如果是算上tiff后面的42版本号,长度则为4。长度大小和CheckSignature相关。

CheckSignature用于匹配图像文件的标志。如果对应的图像不需要标志,则可以在从GrFmtFilterFactory派生的
子类中将其屏蔽。

CheckExtension匹配图像文件名的后缀名,用于也可以自己重新实现。

NewReader/NewWriter为读写驱动对应的构造函数,利用它们可以针对不同图像构造相应的驱动。

工厂类链表定义如下:

class GrFmtFactoriesList
{
public:

GrFmtFactoriesList();
virtual ~GrFmtFactoriesList();
void RemoveAll();
bool AddFactory( GrFmtFilterFactory* factory );
int FactoriesCount() { return m_curFactories; };
ListPosition GetFirstFactoryPos();
GrFmtFilterFactory* GetNextFactory( ListPosition& pos );
virtual GrFmtReader* FindReader( const char* filename );
virtual GrFmtWriter* FindWriter( const char* filename );

protected:

GrFmtFilterFactory** m_factories;
int m_maxFactories;
int m_curFactories;
};

FindReader/FindWriter用于查找图像对应的驱动。如果想修改查找的规则,可以通过
GetNextFactory遍历链表来实现。

真正的读写类从GrFmtReader派生,分别对应grfmt_bmp/grfmt_jpeg等各种格式驱动。
然后通过前面的CvImageFilters::CvImageFilters()来讲各个驱动串到g_Filters.m_factories链表中

class GrFmtReader
{
public:

GrFmtReader( const char* filename );
virtual ~GrFmtReader();

int GetWidth() { return m_width; };
int GetHeight() { return m_height; };
bool IsColor() { return m_iscolor; };
int GetDepth() { return m_bit_depth; };
void UseNativeDepth( bool yes ) { m_native_depth = yes; };
bool IsFloat() { return m_isfloat; };

virtual bool ReadHeader() = 0;
virtual bool ReadData( uchar* data, int step, int color ) = 0;
virtual void Close();

protected:

bool m_iscolor;
int m_width; // width of the image ( filled by ReadHeader )
int m_height; // height of the image ( filled by ReadHeader )
int m_bit_depth;// bit depth per channel (normally 8)
char m_filename[_MAX_PATH]; // filename
bool m_native_depth;// use the native bit depth of the image
bool m_isfloat; // is image saved as float or double?
};

 

GrFmtReader比较核心的地方是3个virtual函数,分表用于读图像文件头、读数据、关闭图像文件。
图像文件在读图像头的时候被打开。

对于图像的其他属性,可以通过在子类中直接操作m_iscolor等protected成员完成。

先大概说这么多,下一步将在上述分析的基础上,自己定义一个图像格式,然后提供相应的读写驱动,
然后集成到cvSaveImage/cvLoadImage函数中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值