看一下icvLoadImage这个函数
view plaincopy to clipboardprint?
/*-----------------------------------------------------------------
*虽然根据参数来说有不同的返回数据的方式,一种是IplImage*,一种是矩阵
*的形式,但是实际上而言,内部数据都是通过矩阵在存储,所以这里就不用
*再分两个函数:一个返回IplImage*,一个返回Cmat*。直接返回void*
*---------------------------------------------------------------*/
static void*
icvLoadImage( const char* filename, int flags, bool load_as_matrix )
{
GrFmtReader* reader = 0; //读取器指针。
IplImage* image = 0; //返回图片数据指针。具体结构可以见前面。
CvMat hdr, *matrix = 0; //两个参数应该是与从矩阵中读入是相关的。
int depth = 8;
CV_FUNCNAME( "cvLoadImage" ); //主要是用于处理报错用的。可以不看。
__BEGIN__; //就是一个宏:定义为{所以这行也可以没有
CvSize size; //大小的struct :可以看一下后面的定义:
int iscolor; //如何取颜色的变量.
int cn;
//看一下文件是否为空.有两方面要考虑:指针为空,内容为空。
if( !filename || strlen(filename) == 0 )
CV_ERROR( CV_StsNullPtr, "null filename" );
//g_Filters是LoadSave.cpp文件中的一个静态变量,因为可以重
//复读取一些图片,但是读取图像的接口是不变的,那么在构造好
//之后,就可以不再重复构造。
//reader指向读取图像的处读取器。
reader = g_Filters.FindReader( filename );
if( !reader ) //如果没有找到。
EXIT;
//主要是读取文件头。得到一些基本的信息。
if( !reader->ReadHeader() )
EXIT;
//设置大小。
size.width = reader->GetWidth();
size.height = reader->GetHeight();
//这里如果flags是-1,那么在读取的时候就用文件本身的通道数。
if( flags == -1 )
iscolor = reader->IsColor();
else
{
//每个宏的值可以后面看一下:
//3信道
//(CV_LOAD_IMAGE_COLOR),
//单信道
//(CV_LOAD_IMAGE_GRAYSCALE),
//保持不变
//(CV_LOAD_IMAGE_ANYCOLOR)
//深度指定输入的图像是否转为每个颜色信道每象素8位,或者同输入的图像一样保持不变。
//8位无符号,16位无符号,32位有符号或者32位浮点型。
//CV_LOAD_IMAGE_ANYDEPTH
//如果输入有冲突的标志,将采用较小的数字值
//CV_LOAD_IMAGE_COLOR | CV_LOAD_IMAGE_ANYCOLOR = CV_LOAD_IMAGE_COLOR
//CV_LOAD_IMAGE_ANYCOLOR和CV_LOAD_IMAGE_UNCHANGED是等值的。
//CV_LOAD_IMAGE_ANYCOLOR有着可以和CV_LOAD_IMAGE_ANYDEPTH同时使用的优点,
//所以CV_LOAD_IMAGE_UNCHANGED不再使用了。
//载入最真实的图像,选择CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR。
if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && reader->IsColor()) )
iscolor = 1;
else
iscolor = 0;
if( (flags & CV_LOAD_IMAGE_ANYDEPTH) != 0 )
{
reader->UseNativeDepth(true);
depth = reader->GetDepth();
}
}
//就是看一下是用3色图,还是灰度图。
cn = iscolor ? 3 : 1;
if( load_as_matrix ) //如果是从矩阵读入
{
int type; //设置一下读数据,看一下是不是浮点数.
if(reader->IsFloat() && depth != 8)
type = CV_32F;
else //如果每一个的数较小,那么往8的倍数上取。
type = ( depth <= 8 ) ? CV_8U : ( depth <= 16 ) ? CV_16U : CV_32S;
//建立一个矩阵.注意一下CV_CALL
CV_CALL( matrix = cvCreateMat( size.height, size.width, CV_MAKETYPE(type, cn) ));
}
else
{
int type; //设置一下是不是读入浮点数.
if(reader->IsFloat() && depth != 8)
type = IPL_DEPTH_32F;
else //往8的倍数上取.
type = ( depth <= 8 ) ? IPL_DEPTH_8U : ( depth <= 16 ) ? IPL_DEPTH_16U : IPL_DEPTH_32S;
//建立一个图片。
CV_CALL( image = cvCreateImage( size, type, cn ));
//把数据矩阵设置好。尽管这里返回值不是矩阵的形式,
//其内部结构应该就是一个矩阵。
matrix = cvGetMat( image, &hdr );
}
//把数据读入到矩阵中.如果读取失败,那么就释放数据。
if( !reader->ReadData( matrix->data.ptr, matrix->step, iscolor ))
{
if( load_as_matrix )
cvReleaseMat( &matrix );
else
cvReleaseImage( &image );
EXIT;
}
__END__;
delete reader; //用的是delete,看来应该是前面读取器的复制。
//看一下状态,有没有出错的状态。
if( cvGetErrStatus() < 0 )
{
if( load_as_matrix )
cvReleaseMat( &matrix );
else
cvReleaseImage( &image );
}
//根据不同的情况返回不同的值。
return load_as_matrix ? (void*)matrix : (void*)image;
}
这里应该就是大致辞看了一下这个函数的读取的过程。
其实里面应该还有一很多细节,那么这里从头开始往下讲。
遇到的第一个数据结构就是GrFmtReader ;