1
/*M///////////////////////////////////////////////////////////////////////////////////////
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10
// Intel License Agreement
11
// For Open Source Computer Vision Library
13
// Copyright (C) 2000, Intel Corporation, all rights reserved.
14
// Third party copyrights are property of their respective owners.
16
// Redistribution and use in source and binary forms, with or without modification,
17
// are permitted provided that the following conditions are met:
19
// * Redistribution's of source code must retain the above copyright notice,
20
// this list of conditions and the following disclaimer.
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.
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.
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.
41
#include "precomp.hpp"
49
#include "grfmt_gdal.hpp"
52
/// C++ Standard Libraries
62
* Convert GDAL Palette Interpretation to OpenCV Pixel Type
64
int gdalPaletteInterpretation2OpenCV( GDALPaletteInterp const& paletteInterp, GDALDataType const& gdalType ){
66
switch( paletteInterp ){
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; }
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; }
99
* Convert gdal type to opencv type
101
int gdal2opencv( const GDALDataType& gdalType, const int& channels ){
107
if( channels == 1 ){ return CV_8UC1; }
108
if( channels == 3 ){ return CV_8UC3; }
109
if( channels == 4 ){ return CV_8UC4; }
110
else { return CV_8UC(channels); }
115
if( channels == 1 ){ return CV_16UC1; }
116
if( channels == 3 ){ return CV_16UC3; }
117
if( channels == 4 ){ return CV_16UC4; }
118
else { return CV_16UC(channels); }
123
if( channels == 1 ){ return CV_16SC1; }
124
if( channels == 3 ){ return CV_16SC3; }
125
if( channels == 4 ){ return CV_16SC4; }
126
else { return CV_16SC(channels); }
132
if( channels == 1 ){ return CV_32SC1; }
133
if( channels == 3 ){ return CV_32SC3; }
134
if( channels == 4 ){ return CV_32SC4; }
135
else { return CV_32SC(channels); }
139
if( channels == 1 ){ return CV_32FC1; }
140
if( channels == 3 ){ return CV_32FC3; }
141
if( channels == 4 ){ return CV_32FC4; }
142
else { return CV_32FC(channels); }
146
if( channels == 1 ){ return CV_64FC1; }
147
if( channels == 3 ){ return CV_64FC3; }
148
if( channels == 4 ){ return CV_64FC4; }
149
else { return CV_64FC(channels); }
153
std::cout << "Unknown GDAL Data Type" << std::endl;
154
std::cout << "Type: " << GDALGetDataTypeName(gdalType) << std::endl;
162
* GDAL Decoder Constructor
164
GdalDecoder::GdalDecoder(){
167
// set a dummy signature
169
for( size_t i=0; i<160; i++ ){
173
/// Register the driver
181
* GDAL Decoder Destructor
183
GdalDecoder::~GdalDecoder(){
186
if( m_dataset != NULL ){
194
double range_cast( const GDALDataType& gdalType,
196
const double& value )
200
if( gdalType == GDT_Byte && cvDepth == CV_8U ){
204
if( gdalType == GDT_Byte && (cvDepth == CV_16U || cvDepth == CV_16S)){
209
if( gdalType == GDT_Byte && (cvDepth == CV_32F || cvDepth == CV_32S)){
210
return (value*16777216);
214
if( (gdalType == GDT_UInt16 || gdalType == GDT_Int16) && cvDepth == CV_8U ){
215
return std::floor(value/256.0);
219
if( (gdalType == GDT_UInt16 || gdalType == GDT_Int16) &&
220
( cvDepth == CV_16U || cvDepth == CV_16S )){
224
// float32 -> float32
225
// float64 -> float64
226
if( (gdalType == GDT_Float32 || gdalType == GDT_Float64) &&
227
( cvDepth == CV_32F || cvDepth == CV_64F )){
231
std::cout << GDALGetDataTypeName( gdalType ) << std::endl;
232
std::cout << "warning: unknown range cast requested." << std::endl;
238
* There are some better mpl techniques for doing this.
240
void write_pixel( const double& pixelValue,
241
const GDALDataType& gdalType,
242
const int& gdalChannels,
246
const int& channel ){
249
double newValue = range_cast(gdalType, image.depth(), pixelValue );
251
// input: 1 channel, output: 1 channel
252
if( gdalChannels == 1 && image.channels() == 1 ){
253
if( image.depth() == CV_8U ){ image.ptr<uchar>(row)[col] = newValue; }
254
else if( image.depth() == CV_16U ){ image.ptr<unsigned short>(row)[col] = newValue; }
255
else if( image.depth() == CV_16S ){ image.ptr<short>(row)[col] = newValue; }
256
else if( image.depth() == CV_32S ){ image.ptr<int>(row)[col] = newValue; }
257
else if( image.depth() == CV_32F ){ image.ptr<float>(row)[col] = newValue; }
258
else if( image.depth() == CV_64F ){ image.ptr<double>(row)[col] = newValue; }
259
else{ throw std::runtime_error("Unknown image depth, gdal: 1, img: 1"); }
262
// input: 1 channel, output: 3 channel
263
else if( gdalChannels == 1 && image.channels() == 3 ){
264
if( image.depth() == CV_8U ){ image.ptr<Vec3b>(row)[col] = Vec3b(newValue,newValue,newValue); }
265
else if( image.depth() == CV_16U ){ image.ptr<Vec3s>(row)[col] = Vec3s(newValue,newValue,newValue); }
266
else if( image.depth() == CV_16S ){ image.ptr<Vec3s>(row)[col] = Vec3s(newValue,newValue,newValue); }
267
else if( image.depth() == CV_32S ){ image.ptr<Vec3i>(row)[col] = Vec3i(newValue,newValue,newValue); }
268
else if( image.depth() == CV_32F ){ image.ptr<Vec3f>(row)[col] = Vec3f(newValue,newValue,newValue); }
269
else if( image.depth() == CV_64F ){ image.ptr<Vec3d>(row)[col] = Vec3d(newValue,newValue,newValue); }
270
else{ throw std::runtime_error("Unknown image depth, gdal:1, img: 3"); }
273
// input: 3 channel, output: 1 channel
274
else if( gdalChannels == 3 && image.channels() == 1 ){
275
if( image.depth() == CV_8U ){ image.ptr<uchar>(row)[col] += (newValue/3.0); }
276
else{ throw std::runtime_error("Unknown image depth, gdal:3, img: 1"); }
279
// input: 4 channel, output: 1 channel
280
else if( gdalChannels == 4 && image.channels() == 1 ){
281
if( image.depth() == CV_8U ){ image.ptr<uchar>(row)[col] = newValue; }
282
else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 1"); }
285
// input: 3 channel, output: 3 channel
286
else if( gdalChannels == 3 && image.channels() == 3 ){
287
if( image.depth() == CV_8U ){ image.at<Vec3b>(row,col)[channel] = newValue; }
288
else if( image.depth() == CV_16U ){ image.ptr<Vec3s>(row,col)[channel] = newValue; }
289
else if( image.depth() == CV_16S ){ image.ptr<Vec3s>(row,col)[channel] = newValue; }
290
else if( image.depth() == CV_32S ){ image.ptr<Vec3i>(row,col)[channel] = newValue; }
291
else if( image.depth() == CV_32F ){ image.ptr<Vec3f>(row,col)[channel] = newValue; }
292
else if( image.depth() == CV_64F ){ image.ptr<Vec3d>(row,col)[channel] = newValue; }
293
else{ throw std::runtime_error("Unknown image depth, gdal: 3, image: 3"); }
296
// input: 4 channel, output: 3 channel
297
else if( gdalChannels == 4 && image.channels() == 3 ){
298
if( channel >= 4 ){ return; }
299
else if( image.depth() == CV_8U && channel < 4 ){ image.ptr<Vec3b>(row,col)[channel] = newValue; }
300
else if( image.depth() == CV_16U && channel < 4 ){ image.ptr<Vec3s>(row,col)[channel] = newValue; }
301
else if( image.depth() == CV_16S && channel < 4 ){ image.ptr<Vec3s>(row,col)[channel] = newValue; }
302
else if( image.depth() == CV_32S && channel < 4 ){ image.ptr<Vec3i>(row,col)[channel] = newValue; }
303
else if( image.depth() == CV_32F && channel < 4 ){ image.ptr<Vec3f>(row,col)[channel] = newValue; }
304
else if( image.depth() == CV_64F && channel < 4 ){ image.ptr<Vec3d>(row,col)[channel] = newValue; }
305
else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 3"); }
308
// input: 4 channel, output: 4 channel
309
else if( gdalChannels == 4 && image.channels() == 4 ){
310
if( image.depth() == CV_8U ){ image.at<Vec4b>(row,col)[channel] = newValue; }
311
else{ throw std::runtime_error("Unknown image depth, gdal: 4, image: 4"); }
314
// input: > 4 channels, output: > 4 channels
315
else if( gdalChannels > 4 && image.channels() > 4 ){
316
if( image.depth() == CV_8U ){ image.ptr<uchar>(row,col)[channel] = newValue; }
317
else if( image.depth() == CV_16U ){ image.ptr<unsigned short>(row,col)[channel] = newValue; }
318
else if( image.depth() == CV_16S ){ image.ptr<short>(row,col)[channel] = newValue; }
319
else if( image.depth() == CV_32S ){ image.ptr<int>(row,col)[channel] = newValue; }
320
else if( image.depth() == CV_32F ){ image.ptr<float>(row,col)[channel] = newValue; }
321
else if( image.depth() == CV_64F ){ image.ptr<double>(row,col)[channel] = newValue; }
322
else{ throw std::runtime_error("Unknown image depth, gdal: N, img: N"); }
324
// otherwise, throw an error
326
throw std::runtime_error("error: can't convert types.");
332
void write_ctable_pixel( const double& pixelValue,
333
const GDALDataType& gdalType,
334
GDALColorTable const* gdalColorTable,
340
if( gdalColorTable == NULL ){
341
write_pixel( pixelValue, gdalType, 1, image, y, x, c );
344
// if we are Grayscale, then do a straight conversion
345
if( gdalColorTable->GetPaletteInterpretation() == GPI_Gray ){
346
write_pixel( pixelValue, gdalType, 1, image, y, x, c );
349
// if we are rgb, then convert here
350
else if( gdalColorTable->GetPaletteInterpretation() == GPI_RGB ){
353
short r = gdalColorTable->GetColorEntry( (int)pixelValue )->c1;
354
short g = gdalColorTable->GetColorEntry( (int)pixelValue )->c2;
355
short b = gdalColorTable->GetColorEntry( (int)pixelValue )->c3;
356
short a = gdalColorTable->GetColorEntry( (int)pixelValue )->c4;
358
write_pixel( r, gdalType, 4, image, y, x, 2 );
359
write_pixel( g, gdalType, 4, image, y, x, 1 );
360
write_pixel( b, gdalType, 4, image, y, x, 0 );
361
if( image.channels() > 3 ){
362
write_pixel( a, gdalType, 4, image, y, x, 1 );
366
// otherwise, set zeros
368
write_pixel( pixelValue, gdalType, 1, image, y, x, c );
377
bool GdalDecoder::readData( Mat& img ){
380
// make sure the image is the proper size
381
if( img.size().height != m_height ){
384
if( img.size().width != m_width ){
388
// make sure the raster is alive
389
if( m_dataset == NULL || m_driver == NULL ){
393
// set the image to zero
397
// iterate over each raster band
398
// note that OpenCV does bgr rather than rgb
399
int nChannels = m_dataset->GetRasterCount();
401
GDALColorTable* gdalColorTable = NULL;
402
if( m_dataset->GetRasterBand(1)->GetColorTable() != NULL ){
403
gdalColorTable = m_dataset->GetRasterBand(1)->GetColorTable();
406
const GDALDataType gdalType = m_dataset->GetRasterBand(1)->GetRasterDataType();
409
if( nChannels > img.channels() ){
410
nChannels = img.channels();
413
for( int c = 0; c<nChannels; c++ ){
416
GDALRasterBand* band = m_dataset->GetRasterBand(c+1);
418
// make sure the image band has the same dimensions as the image
419
if( band->GetXSize() != m_width || band->GetYSize() != m_height ){ return false; }
421
// grab the raster size
422
nRows = band->GetYSize();
423
nCols = band->GetXSize();
425
// create a temporary scanline pointer to store data
426
double* scanline = new double[nCols];
428
// iterate over each row and column
429
for( int y=0; y<nRows; y++ ){
431
// get the entire row
432
band->RasterIO( GF_Read, 0, y, nCols, 1, scanline, nCols, 1, GDT_Float64, 0, 0);
434
// set inside the image
435
for( int x=0; x<nCols; x++ ){
437
// set depending on image types
438
// given boost, I would use enable_if to speed up. Avoid for now.
439
if( hasColorTable == false ){
440
write_pixel( scanline[x], gdalType, nChannels, img, y, x, c );
443
write_ctable_pixel( scanline[x], gdalType, gdalColorTable, img, y, x, c );
448
// delete our temp pointer
461
bool GdalDecoder::readHeader(){
464
m_dataset = (GDALDataset*) GDALOpen( m_filename.c_str(), GA_ReadOnly);
466
// if dataset is null, then there was a problem
467
if( m_dataset == NULL ){
471
// make sure we have pixel data inside the raster
472
if( m_dataset->GetRasterCount() <= 0 ){
476
//extract the driver infomation
477
m_driver = m_dataset->GetDriver();
479
// if the driver failed, then exit
480
if( m_driver == NULL ){
485
// get the image dimensions
486
m_width = m_dataset->GetRasterXSize();
487
m_height= m_dataset->GetRasterYSize();
489
// make sure we have at least one band/channel
490
if( m_dataset->GetRasterCount() <= 0 ){
494
// check if we have a color palette
496
if( m_dataset->GetRasterBand(1)->GetColorInterpretation() == GCI_PaletteIndex ){
498
// remember that we have a color palette
499
hasColorTable = true;
501
// if the color tables does not exist, then we failed
502
if( m_dataset->GetRasterBand(1)->GetColorTable() == NULL ){
506
// otherwise, get the pixeltype
508
// convert the palette interpretation to opencv type
509
tempType = gdalPaletteInterpretation2OpenCV( m_dataset->GetRasterBand(1)->GetColorTable()->GetPaletteInterpretation(),
510
m_dataset->GetRasterBand(1)->GetRasterDataType() );
512
if( tempType == -1 ){
520
// otherwise, we have standard channels
523
// remember that we don't have a color table
524
hasColorTable = false;
526
// convert the datatype to opencv
527
tempType = gdal2opencv( m_dataset->GetRasterBand(1)->GetRasterDataType(), m_dataset->GetRasterCount() );
528
if( tempType == -1 ){
540
void GdalDecoder::close(){
543
GDALClose((GDALDatasetH)m_dataset);
549
* Create a new decoder
551
ImageDecoder GdalDecoder::newDecoder()const{
552
return makePtr<GdalDecoder>();
556
* Test the file signature
558
bool GdalDecoder::checkSignature( const String& signature )const{
562
std::string str = signature.c_str();
563
if( str.substr(0,4).find("NITF") != std::string::npos ){
568
if( str.substr(140,4) == "DTED" ){
575
} /// End of cv Namespace
577
#endif /**< End of HAVE_GDAL Definition */
b'\\ No newline at end of file'