This source file includes following definitions.
- gdalPaletteInterpretation2OpenCV
- gdal2opencv
- range_cast
- write_pixel
- write_ctable_pixel
- readData
- readHeader
- close
- newDecoder
- checkSignature
#include "precomp.hpp"
#include "cvconfig.h"
#ifdef HAVE_GDAL
#include "grfmt_gdal.hpp"
#include <iostream>
#include <stdexcept>
#include <string>
namespace cv{
int gdalPaletteInterpretation2OpenCV( GDALPaletteInterp const& paletteInterp, GDALDataType const& gdalType ){
switch( paletteInterp ){
case GPI_Gray:
if( gdalType == GDT_Byte ){ return CV_8UC1; }
if( gdalType == GDT_UInt16 ){ return CV_16UC1; }
if( gdalType == GDT_Int16 ){ return CV_16SC1; }
if( gdalType == GDT_UInt32 ){ return CV_32SC1; }
if( gdalType == GDT_Int32 ){ return CV_32SC1; }
if( gdalType == GDT_Float32 ){ return CV_32FC1; }
if( gdalType == GDT_Float64 ){ return CV_64FC1; }
return -1;
case GPI_RGB:
if( gdalType == GDT_Byte ){ return CV_8UC1; }
if( gdalType == GDT_UInt16 ){ return CV_16UC3; }
if( gdalType == GDT_Int16 ){ return CV_16SC3; }
if( gdalType == GDT_UInt32 ){ return CV_32SC3; }
if( gdalType == GDT_Int32 ){ return CV_32SC3; }
if( gdalType == GDT_Float32 ){ return CV_32FC3; }
if( gdalType == GDT_Float64 ){ return CV_64FC3; }
return -1;
default:
return -1;
}
}
int gdal2opencv( const GDALDataType& gdalType, const int& channels ){
switch( gdalType ){
case GDT_Byte:
if( channels == 1 ){ return CV_8UC1; }
if( channels == 3 ){ return CV_8UC3; }
if( channels == 4 ){ return CV_8UC4; }
return -1;
case GDT_UInt16:
if( channels == 1 ){ return CV_16UC1; }
if( channels == 3 ){ return CV_16UC3; }
if( channels == 4 ){ return CV_16UC4; }
return -1;
case GDT_Int16:
if( channels == 1 ){ return CV_16SC1; }
if( channels == 3 ){ return CV_16SC3; }
if( channels == 4 ){ return CV_16SC4; }
return -1;
case GDT_UInt32:
case GDT_Int32:
if( channels == 1 ){ return CV_32SC1; }
if( channels == 3 ){ return CV_32SC3; }
if( channels == 4 ){ return CV_32SC4; }
return -1;
default:
std::cout << "Unknown GDAL Data Type" << std::endl;
std::cout << "Type: " << GDALGetDataTypeName(gdalType) << std::endl;
return -1;
}
return -1;
}
GdalDecoder::GdalDecoder(){
m_signature="0";
for( size_t i=0; i<160; i++ ){
m_signature += "0";
}
GDALAllRegister();
m_driver = NULL;
m_dataset = NULL;
}
GdalDecoder::~GdalDecoder(){
if( m_dataset != NULL ){
close();
}
}
double range_cast( const GDALDataType& gdalType,
const int& cvDepth,
const double& value )
{
if( gdalType == GDT_Byte && cvDepth == CV_8U ){
return value;
}
if( gdalType == GDT_Byte && (cvDepth == CV_16U || cvDepth == CV_16S)){
return (value*256);
}
if( gdalType == GDT_Byte && (cvDepth == CV_32F || cvDepth == CV_32S)){
return (value*16777216);
}
if( (gdalType == GDT_UInt16 || gdalType == GDT_Int16) && cvDepth == CV_8U ){
return std::floor(value/256.0);
}
if( (gdalType == GDT_UInt16 || gdalType == GDT_Int16) &&
( cvDepth == CV_16U || cvDepth == CV_16S )){
return value;
}
std::cout << GDALGetDataTypeName( gdalType ) << std::endl;
std::cout << "warning: unknown range cast requested." << std::endl;
return (value);
}
void write_pixel( const double& pixelValue,
const GDALDataType& gdalType,
const int& gdalChannels,
Mat& image,
const int& row,
const int& col,
const int& channel ){
double newValue = range_cast(gdalType, image.depth(), pixelValue );
if( gdalChannels == 1 && image.channels() == 1 ){
if( image.depth() == CV_8U ){ image.at<uchar>(row,col) = newValue; }
else if( image.depth() == CV_16U ){ image.at<unsigned short>(row,col) = newValue; }
else if( image.depth() == CV_16S ){ image.at<short>(row,col) = newValue; }
else if( image.depth() == CV_32S ){ image.at<int>(row,col) = newValue; }
else if( image.depth() == CV_32F ){ image.at<float>(row,col) = newValue; }
else if( image.depth() == CV_64F ){ image.at<double>(row,col) = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: 1, img: 1"); }
}
else if( gdalChannels == 1 && image.channels() == 3 ){
if( image.depth() == CV_8U ){ image.at<Vec3b>(row,col) = Vec3b(newValue,newValue,newValue); }
else if( image.depth() == CV_16U ){ image.at<Vec3s>(row,col) = Vec3s(newValue,newValue,newValue); }
else if( image.depth() == CV_16S ){ image.at<Vec3s>(row,col) = Vec3s(newValue,newValue,newValue); }
else if( image.depth() == CV_32S ){ image.at<Vec3i>(row,col) = Vec3i(newValue,newValue,newValue); }
else if( image.depth() == CV_32F ){ image.at<Vec3f>(row,col) = Vec3f(newValue,newValue,newValue); }
else if( image.depth() == CV_64F ){ image.at<Vec3d>(row,col) = Vec3d(newValue,newValue,newValue); }
else{ throw std::runtime_error("Unknown image depth, gdal:1, img: 3"); }
}
else if( gdalChannels == 3 && image.channels() == 1 ){
if( image.depth() == CV_8U ){ image.at<uchar>(row,col) += (newValue/3.0); }
else{ throw std::runtime_error("Unknown image depth, gdal:3, img: 1"); }
}
else if( gdalChannels == 4 && image.channels() == 1 ){
if( image.depth() == CV_8U ){ image.at<uchar>(row,col) = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 1"); }
}
else if( gdalChannels == 3 && image.channels() == 3 ){
if( image.depth() == CV_8U ){ image.at<Vec3b>(row,col)[channel] = newValue; }
else if( image.depth() == CV_16U ){ image.at<Vec3s>(row,col)[channel] = newValue; }
else if( image.depth() == CV_16S ){ image.at<Vec3s>(row,col)[channel] = newValue; }
else if( image.depth() == CV_32S ){ image.at<Vec3i>(row,col)[channel] = newValue; }
else if( image.depth() == CV_32F ){ image.at<Vec3f>(row,col)[channel] = newValue; }
else if( image.depth() == CV_64F ){ image.at<Vec3d>(row,col)[channel] = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: 3, image: 3"); }
}
else if( gdalChannels == 4 && image.channels() == 3 ){
if( channel >= 4 ){ return; }
else if( image.depth() == CV_8U && channel < 4 ){ image.at<Vec3b>(row,col)[channel] = newValue; }
else if( image.depth() == CV_16U && channel < 4 ){ image.at<Vec3s>(row,col)[channel] = newValue; }
else if( image.depth() == CV_16S && channel < 4 ){ image.at<Vec3s>(row,col)[channel] = newValue; }
else if( image.depth() == CV_32S && channel < 4 ){ image.at<Vec3i>(row,col)[channel] = newValue; }
else if( image.depth() == CV_32F && channel < 4 ){ image.at<Vec3f>(row,col)[channel] = newValue; }
else if( image.depth() == CV_64F && channel < 4 ){ image.at<Vec3d>(row,col)[channel] = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 3"); }
}
else if( gdalChannels == 4 && image.channels() == 4 ){
if( image.depth() == CV_8U ){ image.at<Vec4b>(row,col)[channel] = newValue; }
else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 4"); }
}
else{
throw std::runtime_error("error: can't convert types.");
}
}
void write_ctable_pixel( const double& pixelValue,
const GDALDataType& gdalType,
GDALColorTable const* gdalColorTable,
Mat& image,
const int& y,
const int& x,
const int& c ){
if( gdalColorTable == NULL ){
write_pixel( pixelValue, gdalType, 1, image, y, x, c );
}
if( gdalColorTable->GetPaletteInterpretation() == GPI_Gray ){
write_pixel( pixelValue, gdalType, 1, image, y, x, c );
}
else if( gdalColorTable->GetPaletteInterpretation() == GPI_RGB ){
short r = gdalColorTable->GetColorEntry( (int)pixelValue )->c1;
short g = gdalColorTable->GetColorEntry( (int)pixelValue )->c2;
short b = gdalColorTable->GetColorEntry( (int)pixelValue )->c3;
short a = gdalColorTable->GetColorEntry( (int)pixelValue )->c4;
write_pixel( r, gdalType, 4, image, y, x, 2 );
write_pixel( g, gdalType, 4, image, y, x, 1 );
write_pixel( b, gdalType, 4, image, y, x, 0 );
if( image.channels() > 3 ){
write_pixel( a, gdalType, 4, image, y, x, 1 );
}
}
else{
write_pixel( pixelValue, gdalType, 1, image, y, x, c );
}
}
bool GdalDecoder::readData( Mat& img ){
if( img.size().height != m_height ){
return false;
}
if( img.size().width != m_width ){
return false;
}
if( m_dataset == NULL || m_driver == NULL ){
return false;
}
img = 0;
int nChannels = m_dataset->GetRasterCount();
GDALColorTable* gdalColorTable = NULL;
if( m_dataset->GetRasterBand(1)->GetColorTable() != NULL ){
gdalColorTable = m_dataset->GetRasterBand(1)->GetColorTable();
}
const GDALDataType gdalType = m_dataset->GetRasterBand(1)->GetRasterDataType();
int nRows, nCols;
if( nChannels > img.channels() ){
nChannels = img.channels();
}
for( int c = 0; c<nChannels; c++ ){
GDALRasterBand* band = m_dataset->GetRasterBand(c+1);
if( band->GetXSize() != m_width || band->GetYSize() != m_height ){ return false; }
nRows = band->GetYSize();
nCols = band->GetXSize();
double* scanline = new double[nCols];
for( int y=0; y<nRows; y++ ){
band->RasterIO( GF_Read, 0, y, nCols, 1, scanline, nCols, 1, GDT_Float64, 0, 0);
for( int x=0; x<nCols; x++ ){
if( hasColorTable == false ){
write_pixel( scanline[x], gdalType, nChannels, img, y, x, c );
}
else{
write_ctable_pixel( scanline[x], gdalType, gdalColorTable, img, y, x, c );
}
}
}
delete [] scanline;
}
return true;
}
bool GdalDecoder::readHeader(){
m_dataset = (GDALDataset*) GDALOpen( m_filename.c_str(), GA_ReadOnly);
if( m_dataset == NULL ){
return false;
}
if( m_dataset->GetRasterCount() <= 0 ){
return false;
}
m_driver = m_dataset->GetDriver();
if( m_driver == NULL ){
return false;
}
m_width = m_dataset->GetRasterXSize();
m_height= m_dataset->GetRasterYSize();
if( m_dataset->GetRasterCount() <= 0 ){
return false;
}
int tempType;
if( m_dataset->GetRasterBand(1)->GetColorInterpretation() == GCI_PaletteIndex ){
hasColorTable = true;
if( m_dataset->GetRasterBand(1)->GetColorTable() == NULL ){
return false;
}
else{
tempType = gdalPaletteInterpretation2OpenCV( m_dataset->GetRasterBand(1)->GetColorTable()->GetPaletteInterpretation(),
m_dataset->GetRasterBand(1)->GetRasterDataType() );
if( tempType == -1 ){
return false;
}
m_type = tempType;
}
}
else{
hasColorTable = false;
tempType = gdal2opencv( m_dataset->GetRasterBand(1)->GetRasterDataType(), m_dataset->GetRasterCount() );
if( tempType == -1 ){
return false;
}
m_type = tempType;
}
return true;
}
void GdalDecoder::close(){
GDALClose((GDALDatasetH)m_dataset);
m_dataset = NULL;
m_driver = NULL;
}
ImageDecoder GdalDecoder::newDecoder()const{
return makePtr<GdalDecoder>();
}
bool GdalDecoder::checkSignature( const String& signature )const{
std::string str = signature.c_str();
if( str.substr(0,4).find("NITF") != std::string::npos ){
return true;
}
if( str.substr(140,4) == "DTED" ){
return true;
}
return false;
}
}
#endif