Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective owners.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 #include "precomp.hpp"
     42 
     43 // GDAL Macros
     44 #include "cvconfig.h"
     45 
     46 #ifdef HAVE_GDAL
     47 
     48 // Our Header
     49 #include "grfmt_gdal.hpp"
     50 
     51 
     52 /// C++ Standard Libraries
     53 #include <iostream>
     54 #include <stdexcept>
     55 #include <string>
     56 
     57 
     58 namespace cv{
     59 
     60 
     61 /**
     62  * Convert GDAL Palette Interpretation to OpenCV Pixel Type
     63 */
     64 int  gdalPaletteInterpretation2OpenCV( GDALPaletteInterp const& paletteInterp, GDALDataType const& gdalType ){
     65 
     66     switch( paletteInterp ){
     67 
     68         /// GRAYSCALE
     69         case GPI_Gray:
     70             if( gdalType == GDT_Byte    ){ return CV_8UC1;  }
     71             if( gdalType == GDT_UInt16  ){ return CV_16UC1; }
     72             if( gdalType == GDT_Int16   ){ return CV_16SC1; }
     73             if( gdalType == GDT_UInt32  ){ return CV_32SC1; }
     74             if( gdalType == GDT_Int32   ){ return CV_32SC1; }
     75             if( gdalType == GDT_Float32 ){ return CV_32FC1; }
     76             if( gdalType == GDT_Float64 ){ return CV_64FC1; }
     77             return -1;
     78 
     79         /// RGB
     80         case GPI_RGB:
     81             if( gdalType == GDT_Byte    ){ return CV_8UC1;  }
     82             if( gdalType == GDT_UInt16  ){ return CV_16UC3; }
     83             if( gdalType == GDT_Int16   ){ return CV_16SC3; }
     84             if( gdalType == GDT_UInt32  ){ return CV_32SC3; }
     85             if( gdalType == GDT_Int32   ){ return CV_32SC3; }
     86             if( gdalType == GDT_Float32 ){ return CV_32FC3; }
     87             if( gdalType == GDT_Float64 ){ return CV_64FC3; }
     88             return -1;
     89 
     90 
     91         /// otherwise
     92         default:
     93             return -1;
     94 
     95     }
     96 }
     97 
     98 /**
     99  * Convert gdal type to opencv type
    100 */
    101 int gdal2opencv( const GDALDataType& gdalType, const int& channels ){
    102 
    103     switch( gdalType ){
    104 
    105         /// UInt8
    106         case GDT_Byte:
    107             if( channels == 1 ){ return CV_8UC1; }
    108             if( channels == 3 ){ return CV_8UC3; }
    109             if( channels == 4 ){ return CV_8UC4; }
    110             return -1;
    111 
    112         /// UInt16
    113         case GDT_UInt16:
    114             if( channels == 1 ){ return CV_16UC1; }
    115             if( channels == 3 ){ return CV_16UC3; }
    116             if( channels == 4 ){ return CV_16UC4; }
    117             return -1;
    118 
    119         /// Int16
    120         case GDT_Int16:
    121             if( channels == 1 ){ return CV_16SC1; }
    122             if( channels == 3 ){ return CV_16SC3; }
    123             if( channels == 4 ){ return CV_16SC4; }
    124             return -1;
    125 
    126         /// UInt32
    127         case GDT_UInt32:
    128         case GDT_Int32:
    129             if( channels == 1 ){ return CV_32SC1; }
    130             if( channels == 3 ){ return CV_32SC3; }
    131             if( channels == 4 ){ return CV_32SC4; }
    132             return -1;
    133 
    134         default:
    135             std::cout << "Unknown GDAL Data Type" << std::endl;
    136             std::cout << "Type: " << GDALGetDataTypeName(gdalType) << std::endl;
    137             return -1;
    138     }
    139 
    140     return -1;
    141 }
    142 
    143 /**
    144  * GDAL Decoder Constructor
    145 */
    146 GdalDecoder::GdalDecoder(){
    147 
    148 
    149     // set a dummy signature
    150     m_signature="0";
    151     for( size_t i=0; i<160; i++ ){
    152         m_signature += "0";
    153     }
    154 
    155     /// Register the driver
    156     GDALAllRegister();
    157 
    158     m_driver = NULL;
    159     m_dataset = NULL;
    160 }
    161 
    162 /**
    163  * GDAL Decoder Destructor
    164 */
    165 GdalDecoder::~GdalDecoder(){
    166 
    167 
    168     if( m_dataset != NULL ){
    169        close();
    170     }
    171 }
    172 
    173 /**
    174  * Convert data range
    175 */
    176 double range_cast( const GDALDataType& gdalType,
    177                    const int& cvDepth,
    178                    const double& value )
    179 {
    180 
    181     // uint8 -> uint8
    182     if( gdalType == GDT_Byte && cvDepth == CV_8U ){
    183         return value;
    184     }
    185     // uint8 -> uint16
    186     if( gdalType == GDT_Byte && (cvDepth == CV_16U || cvDepth == CV_16S)){
    187         return (value*256);
    188     }
    189 
    190     // uint8 -> uint32
    191     if( gdalType == GDT_Byte && (cvDepth == CV_32F || cvDepth == CV_32S)){
    192         return (value*16777216);
    193     }
    194 
    195     // int16 -> uint8
    196     if( (gdalType == GDT_UInt16 || gdalType == GDT_Int16) && cvDepth == CV_8U ){
    197         return std::floor(value/256.0);
    198     }
    199 
    200     // int16 -> int16
    201     if( (gdalType == GDT_UInt16 || gdalType == GDT_Int16) &&
    202         ( cvDepth == CV_16U     ||  cvDepth == CV_16S   )){
    203         return value;
    204     }
    205 
    206     std::cout << GDALGetDataTypeName( gdalType ) << std::endl;
    207     std::cout << "warning: unknown range cast requested." << std::endl;
    208     return (value);
    209 }
    210 
    211 
    212 /**
    213  * There are some better mpl techniques for doing this.
    214 */
    215 void write_pixel( const double& pixelValue,
    216                   const GDALDataType& gdalType,
    217                   const int& gdalChannels,
    218                   Mat& image,
    219                   const int& row,
    220                   const int& col,
    221                   const int& channel ){
    222 
    223     // convert the pixel
    224     double newValue = range_cast(gdalType, image.depth(), pixelValue );
    225 
    226     // input: 1 channel, output: 1 channel
    227     if( gdalChannels == 1 && image.channels() == 1 ){
    228         if( image.depth() == CV_8U ){       image.at<uchar>(row,col)          = newValue; }
    229         else if( image.depth() == CV_16U ){ image.at<unsigned short>(row,col) = newValue; }
    230         else if( image.depth() == CV_16S ){ image.at<short>(row,col)          = newValue; }
    231         else if( image.depth() == CV_32S ){ image.at<int>(row,col)            = newValue; }
    232         else if( image.depth() == CV_32F ){ image.at<float>(row,col)          = newValue; }
    233         else if( image.depth() == CV_64F ){ image.at<double>(row,col)         = newValue; }
    234         else{ throw std::runtime_error("Unknown image depth, gdal: 1, img: 1"); }
    235     }
    236 
    237     // input: 1 channel, output: 3 channel
    238     else if( gdalChannels == 1 && image.channels() == 3 ){
    239         if( image.depth() == CV_8U ){   image.at<Vec3b>(row,col) = Vec3b(newValue,newValue,newValue); }
    240         else if( image.depth() == CV_16U ){  image.at<Vec3s>(row,col) = Vec3s(newValue,newValue,newValue); }
    241         else if( image.depth() == CV_16S ){  image.at<Vec3s>(row,col) = Vec3s(newValue,newValue,newValue); }
    242         else if( image.depth() == CV_32S ){  image.at<Vec3i>(row,col) = Vec3i(newValue,newValue,newValue); }
    243         else if( image.depth() == CV_32F ){  image.at<Vec3f>(row,col) = Vec3f(newValue,newValue,newValue); }
    244         else if( image.depth() == CV_64F ){  image.at<Vec3d>(row,col) = Vec3d(newValue,newValue,newValue); }
    245         else{                          throw std::runtime_error("Unknown image depth, gdal:1, img: 3"); }
    246     }
    247 
    248     // input: 3 channel, output: 1 channel
    249     else if( gdalChannels == 3 && image.channels() == 1 ){
    250         if( image.depth() == CV_8U ){   image.at<uchar>(row,col) += (newValue/3.0); }
    251         else{ throw std::runtime_error("Unknown image depth, gdal:3, img: 1"); }
    252     }
    253 
    254     // input: 4 channel, output: 1 channel
    255     else if( gdalChannels == 4 && image.channels() == 1 ){
    256         if( image.depth() == CV_8U ){   image.at<uchar>(row,col) = newValue;  }
    257         else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 1"); }
    258     }
    259 
    260     // input: 3 channel, output: 3 channel
    261     else if( gdalChannels == 3 && image.channels() == 3 ){
    262         if( image.depth() == CV_8U ){  image.at<Vec3b>(row,col)[channel] = newValue;  }
    263         else if( image.depth() == CV_16U ){  image.at<Vec3s>(row,col)[channel] = newValue;  }
    264         else if( image.depth() == CV_16S ){  image.at<Vec3s>(row,col)[channel] = newValue;  }
    265         else if( image.depth() == CV_32S ){  image.at<Vec3i>(row,col)[channel] = newValue;  }
    266         else if( image.depth() == CV_32F ){  image.at<Vec3f>(row,col)[channel] = newValue;  }
    267         else if( image.depth() == CV_64F ){  image.at<Vec3d>(row,col)[channel] = newValue;  }
    268         else{ throw std::runtime_error("Unknown image depth, gdal: 3, image: 3"); }
    269     }
    270 
    271     // input: 4 channel, output: 3 channel
    272     else if( gdalChannels == 4 && image.channels() == 3 ){
    273         if( channel >= 4 ){ return; }
    274         else if( image.depth() == CV_8U  && channel < 4  ){  image.at<Vec3b>(row,col)[channel] = newValue;  }
    275         else if( image.depth() == CV_16U && channel < 4 ){  image.at<Vec3s>(row,col)[channel] = newValue;  }
    276         else if( image.depth() == CV_16S && channel < 4 ){  image.at<Vec3s>(row,col)[channel] = newValue;  }
    277         else if( image.depth() == CV_32S && channel < 4 ){  image.at<Vec3i>(row,col)[channel] = newValue;  }
    278         else if( image.depth() == CV_32F && channel < 4 ){  image.at<Vec3f>(row,col)[channel] = newValue;  }
    279         else if( image.depth() == CV_64F && channel < 4 ){  image.at<Vec3d>(row,col)[channel] = newValue;  }
    280         else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 3"); }
    281     }
    282 
    283     // input: 4 channel, output: 4 channel
    284     else if( gdalChannels == 4 && image.channels() == 4 ){
    285         if( image.depth() == CV_8U ){  image.at<Vec4b>(row,col)[channel] = newValue;  }
    286         else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 4"); }
    287     }
    288 
    289     // otherwise, throw an error
    290     else{
    291         throw std::runtime_error("error: can't convert types.");
    292     }
    293 
    294 }
    295 
    296 
    297 void write_ctable_pixel( const double& pixelValue,
    298                          const GDALDataType& gdalType,
    299                          GDALColorTable const* gdalColorTable,
    300                          Mat& image,
    301                          const int& y,
    302                          const int& x,
    303                          const int& c ){
    304 
    305     if( gdalColorTable == NULL ){
    306        write_pixel( pixelValue, gdalType, 1, image, y, x, c );
    307     }
    308 
    309     // if we are Grayscale, then do a straight conversion
    310     if( gdalColorTable->GetPaletteInterpretation() == GPI_Gray ){
    311         write_pixel( pixelValue, gdalType, 1, image, y, x, c );
    312     }
    313 
    314     // if we are rgb, then convert here
    315     else if( gdalColorTable->GetPaletteInterpretation() == GPI_RGB ){
    316 
    317         // get the pixel
    318         short r = gdalColorTable->GetColorEntry( (int)pixelValue )->c1;
    319         short g = gdalColorTable->GetColorEntry( (int)pixelValue )->c2;
    320         short b = gdalColorTable->GetColorEntry( (int)pixelValue )->c3;
    321         short a = gdalColorTable->GetColorEntry( (int)pixelValue )->c4;
    322 
    323         write_pixel( r, gdalType, 4, image, y, x, 2 );
    324         write_pixel( g, gdalType, 4, image, y, x, 1 );
    325         write_pixel( b, gdalType, 4, image, y, x, 0 );
    326         if( image.channels() > 3 ){
    327             write_pixel( a, gdalType, 4, image, y, x, 1 );
    328         }
    329     }
    330 
    331     // otherwise, set zeros
    332     else{
    333         write_pixel( pixelValue, gdalType, 1, image, y, x, c );
    334     }
    335 }
    336 
    337 
    338 
    339 /**
    340  * read data
    341 */
    342 bool GdalDecoder::readData( Mat& img ){
    343 
    344 
    345     // make sure the image is the proper size
    346     if( img.size().height != m_height ){
    347         return false;
    348     }
    349     if( img.size().width != m_width ){
    350         return false;
    351     }
    352 
    353     // make sure the raster is alive
    354     if( m_dataset == NULL || m_driver == NULL ){
    355         return false;
    356     }
    357 
    358     // set the image to zero
    359     img = 0;
    360 
    361 
    362     // iterate over each raster band
    363     // note that OpenCV does bgr rather than rgb
    364     int nChannels = m_dataset->GetRasterCount();
    365     GDALColorTable* gdalColorTable = NULL;
    366     if( m_dataset->GetRasterBand(1)->GetColorTable() != NULL ){
    367         gdalColorTable = m_dataset->GetRasterBand(1)->GetColorTable();
    368     }
    369 
    370     const GDALDataType gdalType = m_dataset->GetRasterBand(1)->GetRasterDataType();
    371     int nRows, nCols;
    372 
    373     if( nChannels > img.channels() ){
    374         nChannels = img.channels();
    375     }
    376 
    377     for( int c = 0; c<nChannels; c++ ){
    378 
    379         // get the GDAL Band
    380         GDALRasterBand* band = m_dataset->GetRasterBand(c+1);
    381 
    382         // make sure the image band has the same dimensions as the image
    383         if( band->GetXSize() != m_width || band->GetYSize() != m_height ){ return false; }
    384 
    385         // grab the raster size
    386         nRows = band->GetYSize();
    387         nCols = band->GetXSize();
    388 
    389         // create a temporary scanline pointer to store data
    390         double* scanline = new double[nCols];
    391 
    392         // iterate over each row and column
    393         for( int y=0; y<nRows; y++ ){
    394 
    395             // get the entire row
    396             band->RasterIO( GF_Read, 0, y, nCols, 1, scanline, nCols, 1, GDT_Float64, 0, 0);
    397 
    398             // set inside the image
    399             for( int x=0; x<nCols; x++ ){
    400 
    401                 // set depending on image types
    402                 //   given boost, I would use enable_if to speed up.  Avoid for now.
    403                 if( hasColorTable == false ){
    404                     write_pixel( scanline[x], gdalType, nChannels, img, y, x, c );
    405                 }
    406                 else{
    407                     write_ctable_pixel( scanline[x], gdalType, gdalColorTable, img, y, x, c );
    408                 }
    409             }
    410         }
    411 
    412         // delete our temp pointer
    413         delete [] scanline;
    414 
    415 
    416     }
    417 
    418     return true;
    419 }
    420 
    421 
    422 /**
    423  * Read image header
    424 */
    425 bool GdalDecoder::readHeader(){
    426 
    427     // load the dataset
    428     m_dataset = (GDALDataset*) GDALOpen( m_filename.c_str(), GA_ReadOnly);
    429 
    430     // if dataset is null, then there was a problem
    431     if( m_dataset == NULL ){
    432         return false;
    433     }
    434 
    435     // make sure we have pixel data inside the raster
    436     if( m_dataset->GetRasterCount() <= 0 ){
    437         return false;
    438     }
    439 
    440     //extract the driver infomation
    441     m_driver = m_dataset->GetDriver();
    442 
    443     // if the driver failed, then exit
    444     if( m_driver == NULL ){
    445         return false;
    446     }
    447 
    448 
    449     // get the image dimensions
    450     m_width = m_dataset->GetRasterXSize();
    451     m_height= m_dataset->GetRasterYSize();
    452 
    453     // make sure we have at least one band/channel
    454     if( m_dataset->GetRasterCount() <= 0 ){
    455         return false;
    456     }
    457 
    458     // check if we have a color palette
    459     int tempType;
    460     if( m_dataset->GetRasterBand(1)->GetColorInterpretation() == GCI_PaletteIndex ){
    461 
    462         // remember that we have a color palette
    463         hasColorTable = true;
    464 
    465         // if the color tables does not exist, then we failed
    466         if( m_dataset->GetRasterBand(1)->GetColorTable() == NULL ){
    467             return false;
    468         }
    469 
    470         // otherwise, get the pixeltype
    471         else{
    472             // convert the palette interpretation to opencv type
    473             tempType = gdalPaletteInterpretation2OpenCV( m_dataset->GetRasterBand(1)->GetColorTable()->GetPaletteInterpretation(),
    474                                                          m_dataset->GetRasterBand(1)->GetRasterDataType() );
    475 
    476             if( tempType == -1 ){
    477                 return false;
    478             }
    479             m_type = tempType;
    480         }
    481 
    482     }
    483 
    484     // otherwise, we have standard channels
    485     else{
    486 
    487         // remember that we don't have a color table
    488         hasColorTable = false;
    489 
    490         // convert the datatype to opencv
    491         tempType = gdal2opencv( m_dataset->GetRasterBand(1)->GetRasterDataType(), m_dataset->GetRasterCount() );
    492         if( tempType == -1 ){
    493             return false;
    494         }
    495         m_type = tempType;
    496     }
    497 
    498     return true;
    499 }
    500 
    501 /**
    502  * Close the module
    503 */
    504 void GdalDecoder::close(){
    505 
    506 
    507     GDALClose((GDALDatasetH)m_dataset);
    508     m_dataset = NULL;
    509     m_driver = NULL;
    510 }
    511 
    512 /**
    513  * Create a new decoder
    514 */
    515 ImageDecoder GdalDecoder::newDecoder()const{
    516     return makePtr<GdalDecoder>();
    517 }
    518 
    519 /**
    520  * Test the file signature
    521 */
    522 bool GdalDecoder::checkSignature( const String& signature )const{
    523 
    524 
    525     // look for NITF
    526     std::string str = signature.c_str();
    527     if( str.substr(0,4).find("NITF") != std::string::npos ){
    528         return true;
    529     }
    530 
    531     // look for DTED
    532     if( str.substr(140,4) == "DTED" ){
    533         return true;
    534     }
    535 
    536     return false;
    537 }
    538 
    539 } /// End of cv Namespace
    540 
    541 #endif /**< End  of HAVE_GDAL Definition */
    542