opencv--finddecoder函数

在第一篇处,我们只是在最表层的上面操作函数,当别人问我们时,我们其实什么也不知道的。就知道,imread是读取函数了,然后掉用其它的函数的乐乐。当然,上面我们可以好好学习人家为什么要这样做了!这里,看一个函数finddecoder()。这个函数主要是获取decoder对象,从而决定读取什么样后缀名的图像(jpg,bmp等等)

声明:

 

ImageDecoder findDecoder( const string& filename );//在highgui/loadsave.cpp中

ImageDecoder findDecoder( const Mat& buf );

//这个是一个函数的重载了,在第一篇,即imread函数中调用的是第一个,这里就跟进第一个。

定义:

 

ImageDecoder findDecoder( const string& filename )
{
    size_t i, maxlen = 0;
    for( i = 0; i < decoders.size(); i++ )//这里第一个decoders是什么呢?在文件中有这样的一个定义:static vector<ImageDecoder> decoders;好家伙,原来是一个向量,这里第一问,为什么要是一个向量,而且还是全局静态变量,就是说整个程序运行期间它都存在。其只初始化一遍。
    {
        size_t len = decoders[i]->signatureLength();//这一个循环是寻找第一个数据点保存的数据:signature。从这里可以看出,其实后缀名在这里没有什么用处,文件本身是保存了这个类型值的。
        maxlen = std::max(maxlen, len);//读取数据长度为一个最大的。
    }

    FILE* f= fopen( filename.c_str(), "rb" );//熟悉的c函数,读取文件。哈哈,从这个可以看到,所有的文件都可以有FILE来读取的。
    if( !f )
        return ImageDecoder();//没有读取成功,返回一个空的decoder。处理错误的能力。
    string signature(maxlen, ' ');

  maxlen = fread( &signature[0], 1, maxlen, f );//从文件中读取signature数据,这里是用了string,且是按字节读取。string底层用了什么结构呢?string[0]返回的是一个什么值呢?这有待查询。

/*这里是一个试验:

    int maxlen = 10 ;
    string sig(maxlen,' ');
    cout<<&sig<<endl;
    cout<<((int*)&sig[0])<<endl;

   cout<<((int*)&sig[1])<<endl;

  从其中可以看出两个量的值是不同的:

0x22ff40
0x3e3cbc   //这里和后面的数据相差一个字节,代表这是一个char类型的
0x3e3cbd

*/
    fclose(f);
    signature = signature.substr(0, maxlen);

    for( i = 0; i < decoders.size(); i++ )
    {
        if( decoders[i]->checkSignature(signature) )//检测读取出来的数据是否与保存的数据signature一样,一样就代表是这个类型了。
            return decoders[i]->newDecoder();//创建这个类型的decoder变量。
    }

    return ImageDecoder();
}

//下面是decoders数据内容的来源:

struct ImageCodecInitializer
{
    ImageCodecInitializer()
    {
        decoders.push_back( new BmpDecoder );
        encoders.push_back( new BmpEncoder );
    #ifdef HAVE_JPEG
        decoders.push_back( new JpegDecoder );
        encoders.push_back( new JpegEncoder );
    #endif
        decoders.push_back( new SunRasterDecoder );
        encoders.push_back( new SunRasterEncoder );
        decoders.push_back( new PxMDecoder );
        encoders.push_back( new PxMEncoder );
    #ifdef HAVE_TIFF
        decoders.push_back( new TiffDecoder );
    #endif
        encoders.push_back( new TiffEncoder );
    #ifdef HAVE_PNG
        decoders.push_back( new PngDecoder );
        encoders.push_back( new PngEncoder );
    #endif
    #ifdef HAVE_JASPER
        decoders.push_back( new Jpeg2KDecoder );
        encoders.push_back( new Jpeg2KEncoder );
    #endif
    #ifdef HAVE_OPENEXR
        decoders.push_back( new ExrDecoder );
        encoders.push_back( new ExrEncoder );
    #endif
    // because it is a generic image I/O API, supporting many formats,
    // it should be last in the list.
    #ifdef HAVE_IMAGEIO
        decoders.push_back( new ImageIODecoder );
        encoders.push_back( new ImageIOEncoder );
    #endif
    }
};

static ImageCodecInitializer initialize_codecs; //这里直接的给定了decoders的内容。

这样读取图像数据又清晰了一步,首先是我们会首先保存好要解析的图像格式,即支持什么类型的图像。然后第一步是取读取保存在第一个数据点上的signature数据,然后再去读取下面的数据。所以,要很清楚的了解图像的头。

 

 

发布了31 篇原创文章 · 获赞 9 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章