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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章