diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index 699bc163c8..3222321e5b 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -127,6 +127,7 @@ Currently, the following file formats are supported: - TIFF files - \*.tiff, \*.tif (see the *Notes* section) - OpenEXR Image files - \*.exr (see the *Notes* section) - Radiance HDR - \*.hdr, \*.pic (always supported) +- Raster and Vector geospatial data supported by Gdal (see the *Notes* section) @note @@ -141,6 +142,10 @@ Currently, the following file formats are supported: codecs supplied with an OS image. Install the relevant packages (do not forget the development files, for example, "libjpeg-dev", in Debian\* and Ubuntu\*) to get the codec support or turn on the OPENCV_BUILD_3RDPARTY_LIBS flag in CMake. +- In the case you set *WITH_GDAL* flag to true in CMake and @ref IMREAD_LOAD_GDAL to load the image, + then [GDAL](http://www.gdal.org) driver will be used in order to decode the image by supporting + the following formats: [Raster](http://www.gdal.org/formats_list.html), + [Vector](http://www.gdal.org/ogr_formats.html). @param filename Name of file to be loaded. @param flags Flag that can take values of cv::ImreadModes */ diff --git a/modules/imgcodecs/src/grfmt_gdal.cpp b/modules/imgcodecs/src/grfmt_gdal.cpp index 55dd7192f6..1094b91b38 100644 --- a/modules/imgcodecs/src/grfmt_gdal.cpp +++ b/modules/imgcodecs/src/grfmt_gdal.cpp @@ -107,6 +107,7 @@ int gdal2opencv( const GDALDataType& gdalType, const int& channels ){ if( channels == 1 ){ return CV_8UC1; } if( channels == 3 ){ return CV_8UC3; } if( channels == 4 ){ return CV_8UC4; } + else { return CV_8UC(channels); } return -1; /// UInt16 @@ -114,6 +115,7 @@ int gdal2opencv( const GDALDataType& gdalType, const int& channels ){ if( channels == 1 ){ return CV_16UC1; } if( channels == 3 ){ return CV_16UC3; } if( channels == 4 ){ return CV_16UC4; } + else { return CV_16UC(channels); } return -1; /// Int16 @@ -121,6 +123,7 @@ int gdal2opencv( const GDALDataType& gdalType, const int& channels ){ if( channels == 1 ){ return CV_16SC1; } if( channels == 3 ){ return CV_16SC3; } if( channels == 4 ){ return CV_16SC4; } + else { return CV_16SC(channels); } return -1; /// UInt32 @@ -129,6 +132,21 @@ int gdal2opencv( const GDALDataType& gdalType, const int& channels ){ if( channels == 1 ){ return CV_32SC1; } if( channels == 3 ){ return CV_32SC3; } if( channels == 4 ){ return CV_32SC4; } + else { return CV_32SC(channels); } + return -1; + + case GDT_Float32: + if( channels == 1 ){ return CV_32FC1; } + if( channels == 3 ){ return CV_32FC3; } + if( channels == 4 ){ return CV_32FC4; } + else { return CV_32FC(channels); } + return -1; + + case GDT_Float64: + if( channels == 1 ){ return CV_64FC1; } + if( channels == 3 ){ return CV_64FC3; } + if( channels == 4 ){ return CV_64FC4; } + else { return CV_64FC(channels); } return -1; default: @@ -203,6 +221,13 @@ double range_cast( const GDALDataType& gdalType, return value; } + // float32 -> float32 + // float64 -> float64 + if( (gdalType == GDT_Float32 || gdalType == GDT_Float64) && + ( cvDepth == CV_32F || cvDepth == CV_64F )){ + return value; + } + std::cout << GDALGetDataTypeName( gdalType ) << std::endl; std::cout << "warning: unknown range cast requested." << std::endl; return (value); @@ -225,58 +250,58 @@ void write_pixel( const double& pixelValue, // input: 1 channel, output: 1 channel if( gdalChannels == 1 && image.channels() == 1 ){ - if( image.depth() == CV_8U ){ image.at(row,col) = newValue; } - else if( image.depth() == CV_16U ){ image.at(row,col) = newValue; } - else if( image.depth() == CV_16S ){ image.at(row,col) = newValue; } - else if( image.depth() == CV_32S ){ image.at(row,col) = newValue; } - else if( image.depth() == CV_32F ){ image.at(row,col) = newValue; } - else if( image.depth() == CV_64F ){ image.at(row,col) = newValue; } + if( image.depth() == CV_8U ){ image.ptr(row)[col] = newValue; } + else if( image.depth() == CV_16U ){ image.ptr(row)[col] = newValue; } + else if( image.depth() == CV_16S ){ image.ptr(row)[col] = newValue; } + else if( image.depth() == CV_32S ){ image.ptr(row)[col] = newValue; } + else if( image.depth() == CV_32F ){ image.ptr(row)[col] = newValue; } + else if( image.depth() == CV_64F ){ image.ptr(row)[col] = newValue; } else{ throw std::runtime_error("Unknown image depth, gdal: 1, img: 1"); } } // input: 1 channel, output: 3 channel else if( gdalChannels == 1 && image.channels() == 3 ){ - if( image.depth() == CV_8U ){ image.at(row,col) = Vec3b(newValue,newValue,newValue); } - else if( image.depth() == CV_16U ){ image.at(row,col) = Vec3s(newValue,newValue,newValue); } - else if( image.depth() == CV_16S ){ image.at(row,col) = Vec3s(newValue,newValue,newValue); } - else if( image.depth() == CV_32S ){ image.at(row,col) = Vec3i(newValue,newValue,newValue); } - else if( image.depth() == CV_32F ){ image.at(row,col) = Vec3f(newValue,newValue,newValue); } - else if( image.depth() == CV_64F ){ image.at(row,col) = Vec3d(newValue,newValue,newValue); } + if( image.depth() == CV_8U ){ image.ptr(row)[col] = Vec3b(newValue,newValue,newValue); } + else if( image.depth() == CV_16U ){ image.ptr(row)[col] = Vec3s(newValue,newValue,newValue); } + else if( image.depth() == CV_16S ){ image.ptr(row)[col] = Vec3s(newValue,newValue,newValue); } + else if( image.depth() == CV_32S ){ image.ptr(row)[col] = Vec3i(newValue,newValue,newValue); } + else if( image.depth() == CV_32F ){ image.ptr(row)[col] = Vec3f(newValue,newValue,newValue); } + else if( image.depth() == CV_64F ){ image.ptr(row)[col] = Vec3d(newValue,newValue,newValue); } else{ throw std::runtime_error("Unknown image depth, gdal:1, img: 3"); } } // input: 3 channel, output: 1 channel else if( gdalChannels == 3 && image.channels() == 1 ){ - if( image.depth() == CV_8U ){ image.at(row,col) += (newValue/3.0); } + if( image.depth() == CV_8U ){ image.ptr(row)[col] += (newValue/3.0); } else{ throw std::runtime_error("Unknown image depth, gdal:3, img: 1"); } } // input: 4 channel, output: 1 channel else if( gdalChannels == 4 && image.channels() == 1 ){ - if( image.depth() == CV_8U ){ image.at(row,col) = newValue; } + if( image.depth() == CV_8U ){ image.ptr(row)[col] = newValue; } else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 1"); } } // input: 3 channel, output: 3 channel else if( gdalChannels == 3 && image.channels() == 3 ){ if( image.depth() == CV_8U ){ image.at(row,col)[channel] = newValue; } - else if( image.depth() == CV_16U ){ image.at(row,col)[channel] = newValue; } - else if( image.depth() == CV_16S ){ image.at(row,col)[channel] = newValue; } - else if( image.depth() == CV_32S ){ image.at(row,col)[channel] = newValue; } - else if( image.depth() == CV_32F ){ image.at(row,col)[channel] = newValue; } - else if( image.depth() == CV_64F ){ image.at(row,col)[channel] = newValue; } + else if( image.depth() == CV_16U ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_16S ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_32S ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_32F ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_64F ){ image.ptr(row,col)[channel] = newValue; } else{ throw std::runtime_error("Unknown image depth, gdal: 3, image: 3"); } } // input: 4 channel, output: 3 channel else if( gdalChannels == 4 && image.channels() == 3 ){ if( channel >= 4 ){ return; } - else if( image.depth() == CV_8U && channel < 4 ){ image.at(row,col)[channel] = newValue; } - else if( image.depth() == CV_16U && channel < 4 ){ image.at(row,col)[channel] = newValue; } - else if( image.depth() == CV_16S && channel < 4 ){ image.at(row,col)[channel] = newValue; } - else if( image.depth() == CV_32S && channel < 4 ){ image.at(row,col)[channel] = newValue; } - else if( image.depth() == CV_32F && channel < 4 ){ image.at(row,col)[channel] = newValue; } - else if( image.depth() == CV_64F && channel < 4 ){ image.at(row,col)[channel] = newValue; } + else if( image.depth() == CV_8U && channel < 4 ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_16U && channel < 4 ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_16S && channel < 4 ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_32S && channel < 4 ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_32F && channel < 4 ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_64F && channel < 4 ){ image.ptr(row,col)[channel] = newValue; } else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 3"); } } @@ -286,6 +311,16 @@ void write_pixel( const double& pixelValue, else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 4"); } } + // input: > 4 channels, output: > 4 channels + else if( gdalChannels > 4 && image.channels() > 4 ){ + if( image.depth() == CV_8U ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_16U ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_16S ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_32S ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_32F ){ image.ptr(row,col)[channel] = newValue; } + else if( image.depth() == CV_64F ){ image.ptr(row,col)[channel] = newValue; } + else{ throw std::runtime_error("Unknown image depth, gdal: N, img: N"); } + } // otherwise, throw an error else{ throw std::runtime_error("error: can't convert types."); @@ -362,6 +397,7 @@ bool GdalDecoder::readData( Mat& img ){ // iterate over each raster band // note that OpenCV does bgr rather than rgb int nChannels = m_dataset->GetRasterCount(); + GDALColorTable* gdalColorTable = NULL; if( m_dataset->GetRasterBand(1)->GetColorTable() != NULL ){ gdalColorTable = m_dataset->GetRasterBand(1)->GetColorTable(); @@ -538,4 +574,4 @@ bool GdalDecoder::checkSignature( const String& signature )const{ } /// End of cv Namespace -#endif /**< End of HAVE_GDAL Definition */ +#endif /**< End of HAVE_GDAL Definition */ \ No newline at end of file diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 385bab1e1d..70a31c37a2 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -290,7 +290,7 @@ imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 ) // grab the decoded type int type = decoder->type(); - if( flags != IMREAD_UNCHANGED ) + if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED ) { if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 ) type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type)); @@ -382,7 +382,7 @@ imreadmulti_(const String& filename, int flags, std::vector& mats) { // grab the decoded type int type = decoder->type(); - if (flags != IMREAD_UNCHANGED) + if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED ) { if ((flags & CV_LOAD_IMAGE_ANYDEPTH) == 0) type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type)); @@ -521,7 +521,7 @@ imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 ) size.height = decoder->height(); int type = decoder->type(); - if( flags != IMREAD_UNCHANGED ) + if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED ) { if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 ) type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));