pktools  2.6.3
Processing Kernel for geospatial data
ImgReaderGdal.cc
1 /**********************************************************************
2 ImgReaderGdal.cc: class to read raster files using GDAL API library
3 Copyright (C) 2008-2012 Pieter Kempeneers
4 
5 This file is part of pktools
6 
7 pktools is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 pktools is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with pktools. If not, see <http://www.gnu.org/licenses/>.
19 ***********************************************************************/
20 #include "ImgReaderGdal.h"
21 #include <assert.h>
22 #include <sstream>
23 #include <iostream>
24 #include <gsl/gsl_cdf.h>
25 
26 ImgReaderGdal::ImgReaderGdal(void)
27  : m_gds(NULL), m_ncol(0), m_nrow(0), m_nband(0)
28 {}
29 
30 void ImgReaderGdal::open(const std::string& filename)//, double magicX, double magicY)
31 {
32  m_filename = filename;
33  setCodec();//magicX,magicY);
34 }
35 
36 ImgReaderGdal::~ImgReaderGdal(void)
37 {
38  // delete m_gds;
39 // GDALDumpOpenDatasets(stderr);
40 // GDALDestroyDriverManager();//could be used by other objects...
41 }
42 
43 //--------------------------------------------------------------------------
44 void ImgReaderGdal::close(void)
45 {
46  GDALClose(m_gds);
47 }
48 
49 void ImgReaderGdal::setCodec()//double magicX, double magicY)
50 {
51  GDALAllRegister();
52  m_gds = (GDALDataset *) GDALOpen(m_filename.c_str(), GA_ReadOnly );
53  if(m_gds == NULL){
54  std::string errorString="FileOpenError";
55  throw(errorString);
56  }
57  m_ncol= m_gds->GetRasterXSize();
58  m_nrow= m_gds->GetRasterYSize();
59  m_nband= m_gds->GetRasterCount();
60  // m_isGeoRef=( static_cast<std::string>(m_gds->GetProjectionRef()) != "" );
61  // m_magic_x=magicX;
62  // m_magic_y=magicY;
63  double adfGeoTransform[6];
64  m_gds->GetGeoTransform( adfGeoTransform );
65  // if( m_gds->GetGeoTransform( adfGeoTransform ) == CE_None ){
66  m_gt[0]=adfGeoTransform[0];
67  m_gt[1]=adfGeoTransform[1];
68  m_gt[2]=adfGeoTransform[2];
69  m_gt[3]=adfGeoTransform[3];
70  m_gt[4]=adfGeoTransform[4];
71  m_gt[5]=adfGeoTransform[5];
72  // }
73  // else{
74  // m_gt[0]=0;
75  // m_gt[1]=1;
76  // m_gt[2]=0;
77  // m_gt[3]=0;
78  // m_gt[4]=0;
79  // m_gt[5]=1;
80  // }
81 }
82 
83 std::string ImgReaderGdal::getProjection(void) const
84 {
85  std::string theProjection=m_gds->GetProjectionRef();
86  // size_t startpos,endpos;
87  // while((startpos=theProjection.find(",AUTHORITY"))!=std::string::npos){
88  // endpos=theProjection.find("]",startpos+1,1)+1;
89  // theProjection.erase(startpos,endpos-startpos);
90  // }
91  return theProjection;
92 }
93 
94 std::string ImgReaderGdal::getProjectionRef(void) const
95 {
96  std::string theProjection;
97  if(m_gds->GetProjectionRef())
98  return(m_gds->GetProjectionRef());
99  else
100  return "";
101 }
102 
103 GDALDataType ImgReaderGdal::getDataType(int band) const
104 {
105  assert(band<m_nband+1);
106  return (m_gds->GetRasterBand(band+1))->GetRasterDataType();
107 }
108 
109 GDALRasterBand* ImgReaderGdal::getRasterBand(int band)
110 {
111  assert(band<m_nband+1);
112  return (m_gds->GetRasterBand(band+1));
113 }
114 
115 GDALColorTable* ImgReaderGdal::getColorTable(int band) const
116 {
117  assert(band<m_nband+1);
118  return (m_gds->GetRasterBand(band+1))->GetColorTable();
119 }
120 
121 std::string ImgReaderGdal::getDriverDescription() const
122 {
123  return m_gds->GetDriver()->GetDescription();
124 }
125 
126 void ImgReaderGdal::getGeoTransform(double* gt) const{
127  m_gds->GetGeoTransform(gt);
128 }
129 
130 // void ImgReaderGdal::getGeoTransform(double& ulx, double& uly, double& deltaX, double& deltaY, double& rot1, double& rot2) const
131 // {
132 // double adfGeoTransform[6];// { 444720, 30, 0, 3751320, 0, -30 };
133 // m_gds->GetGeoTransform(adfGeoTransform);
134 // ulx=adfGeoTransform[0];
135 // deltaX=adfGeoTransform[1];
136 // rot1=adfGeoTransform[2];
137 // uly=adfGeoTransform[3];
138 // rot2=adfGeoTransform[4];
139 // deltaY=-adfGeoTransform[5];//convention of GDAL!
140 // }
141 
142 std::string ImgReaderGdal::getGeoTransform() const
143 {
144  double gt[6];// { 444720, 30, 0, 3751320, 0, -30 };
145  m_gds->GetGeoTransform(gt);
146  std::ostringstream s;
147  s << "[" << gt[0] << "," << gt[1] << "," << gt[2] << "," << gt[3] << "," << gt[4] << "," << gt[5] << "]";
148  return(s.str());
149  // if(!isGeoRef())
150  // return("");
151  // else{
152  // double adfGeoTransform[6];// { 444720, 30, 0, 3751320, 0, -30 };
153  // m_gds->GetGeoTransform(adfGeoTransform);
154  // double ulx=adfGeoTransform[0];
155  // double deltaX=adfGeoTransform[1];
156  // double rot1=adfGeoTransform[2];
157  // double uly=adfGeoTransform[3];
158  // double rot2=adfGeoTransform[4];
159  // double deltaY=-adfGeoTransform[5];//convention of GDAL!
160  // std::ostringstream s;
161  // s << "[" << ulx << "," << deltaX << "," << rot1 << "," << uly << "," << rot2 << "," << -deltaY << "]";
162  // return(s.str());
163  // }
164 }
165 
166 char** ImgReaderGdal::getMetadata()
167 {
168  if(m_gds->GetMetadata()!=NULL)
169  return(m_gds->GetMetadata());
170  else
171  return (char**)"";
172 }
173 
174 char** ImgReaderGdal::getMetadata() const
175 {
176  if(m_gds->GetMetadata()!=NULL)
177  return(m_gds->GetMetadata());
178  else
179  return (char**)"";
180 }
181 
182 void ImgReaderGdal::getMetadata(std::list<std::string>& metadata) const
183 {
184  char** cmetadata=m_gds->GetMetadata();
185  while(*cmetadata!=NULL){
186  metadata.push_back(*(cmetadata));
187  ++cmetadata;
188  }
189 }
190 
191 std::string ImgReaderGdal::getDescription() const
192 {
193  if(m_gds->GetDriver()->GetDescription()!=NULL)
194  return m_gds->GetDriver()->GetDescription();
195  else
196  return "";
197 }
198 
199 std::string ImgReaderGdal::getMetadataItem() const
200 {
201  if(m_gds->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME )!=NULL)
202  return m_gds->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME );
203  else
204  return "";
205 }
206 std::string ImgReaderGdal::getImageDescription() const
207 {
208  if(m_gds->GetDriver()->GetMetadataItem("TIFFTAG_IMAGEDESCRIPTION")!=NULL)
209  return m_gds->GetDriver()->GetMetadataItem("TIFFTAG_IMAGEDESCRIPTION");
210  else
211  return "";
212 }
213 
214 std::string ImgReaderGdal::getInterleave() const
215 {
216  if(m_gds->GetMetadataItem( "INTERLEAVE", "IMAGE_STRUCTURE"))
217  return m_gds->GetMetadataItem( "INTERLEAVE", "IMAGE_STRUCTURE");
218  else
219  return("BAND");
220 }
221 
222 std::string ImgReaderGdal::getCompression() const
223 {
224  if(m_gds->GetMetadataItem( "COMPRESSION", "IMAGE_STRUCTURE"))
225  return m_gds->GetMetadataItem( "COMPRESSION", "IMAGE_STRUCTURE");
226  else
227  return("NONE");
228 }
229 
230 bool ImgReaderGdal::getBoundingBox(double& ulx, double& uly, double& lrx, double& lry) const
231 {
232  double gt[6];// { 444720, 30, 0, 3751320, 0, -30 };
233  m_gds->GetGeoTransform(gt);
234 
235  //assuming
236  //adfGeotransform[0]: ULX (upper left X coordinate)
237  //adfGeotransform[1]: $cos(\alpha)\cdot\textrm{Xres}$
238  //adfGeotransform[2]: $-sin(\alpha)\cdot\textrm{Xres}$
239  //adfGeotransform[3]: ULY (upper left Y coordinate)
240  //adfGeotransform[4]: $-sin(\alpha)\cdot\textrm{Yres}$
241  //adfGeotransform[5]: $-cos(\alpha)\cdot\textrm{Yres}$
242  ulx=gt[0];
243  uly=gt[3];
244  lrx=gt[0]+nrOfCol()*gt[1]+nrOfRow()*gt[2];
245  lry=gt[3]+nrOfCol()*gt[4]+nrOfRow()*gt[5];
246  if(isGeoRef()){
247  // ulx=m_ulx;
248  // uly=m_uly;
249  // lrx=ulx+nrOfCol()*m_delta_x;
250  // lry=uly-nrOfRow()*m_delta_y;
251  return true;
252  }
253  else{
254  // ulx=0;
255  // uly=nrOfRow()-1;
256  // lrx=nrOfCol()-1;
257  // lry=0;
258  return false;
259  }
260 }
261 
262 bool ImgReaderGdal::getCenterPos(double& x, double& y) const
263 {
264  double gt[6];// { 444720, 30, 0, 3751320, 0, -30 };
265  m_gds->GetGeoTransform(gt);
266 
267  //assuming
268  //adfGeotransform[0]: ULX (upper left X coordinate)
269  //adfGeotransform[1]: $cos(\alpha)\cdot\textrm{Xres}$
270  //adfGeotransform[2]: $-sin(\alpha)\cdot\textrm{Xres}$
271  //adfGeotransform[3]: ULY (upper left Y coordinate)
272  //adfGeotransform[4]: $-sin(\alpha)\cdot\textrm{Yres}$
273  //adfGeotransform[5]: $-cos(\alpha)\cdot\textrm{Yres}$
274  x=gt[0]+(nrOfCol()/2.0)*gt[1]+(nrOfRow()/2.0)*gt[2];
275  y=gt[3]+(nrOfCol()/2.0)*gt[4]+(nrOfRow()/2.0)*gt[5];
276  if(isGeoRef()){
277  // x=m_ulx+(nrOfCol()/2.0)*m_delta_x;
278  // y=m_uly-(nrOfRow()/2.0)*m_delta_y;
279  return true;
280  }
281  else{
282  // x=nrOfCol()/2.0;
283  // y=nrOfRow()/2.0;
284  return false;
285  }
286 }
287 
288 //i and j represent fraction of pixels, return true if image is georeferenced
289 bool ImgReaderGdal::geo2image(double x, double y, double& i, double& j) const
290 {
291  //double values are returned, caller is responsible for interpolation step
292  double gt[6];// { 444720, 30, 0, 3751320, 0, -30 };
293  m_gds->GetGeoTransform(gt);
294  //assuming
295  //adfGeotransform[0]: ULX (upper left X coordinate)
296  //adfGeotransform[1]: $cos(\alpha)\cdot\textrm{Xres}$
297  //adfGeotransform[2]: $-sin(\alpha)\cdot\textrm{Xres}$
298  //adfGeotransform[3]: ULY (upper left Y coordinate)
299  //adfGeotransform[4]: $-sin(\alpha)\cdot\textrm{Yres}$
300  //adfGeotransform[5]: $-cos(\alpha)\cdot\textrm{Yres}$
301 
302  double denom=(gt[1]-gt[2]*gt[4]/gt[5]);
303  double eps=0.00001;
304  if(fabs(denom)>eps){
305  i=(x-gt[0]-gt[2]/gt[5]*(y-gt[3]))/denom;
306  j=(y-gt[3]-gt[4]*(x-gt[0]-gt[2]/gt[5]*(y-gt[3]))/denom)/gt[5];
307  }
308  if(isGeoRef()){
309  // double ulx=m_ulx;
310  // double uly=m_uly;
311  // i=(x-ulx)/m_delta_x;
312  // j=(uly-y)/m_delta_y;
313  return true;
314  }
315  else{
316  // i=x;
317  // j=nrOfRow()-y;
318  return false;
319  }
320 }
321 
322 //x and y represent center of pixel, return true if image is georeferenced
323 bool ImgReaderGdal::image2geo(double i, double j, double& x, double& y) const
324 {
325  double gt[6];// { 444720, 30, 0, 3751320, 0, -30 };
326  m_gds->GetGeoTransform(gt);
327 
328  //assuming
329  //adfGeotransform[0]: ULX (upper left X coordinate)
330  //adfGeotransform[1]: $cos(\alpha)\cdot\textrm{Xres}$
331  //adfGeotransform[2]: $-sin(\alpha)\cdot\textrm{Xres}$
332  //adfGeotransform[3]: ULY (upper left Y coordinate)
333  //adfGeotransform[4]: $-sin(\alpha)\cdot\textrm{Yres}$
334  //adfGeotransform[5]: $-cos(\alpha)\cdot\textrm{Yres}$
335 
336  x=gt[0]+(0.5+i)*gt[1]+(0.5+j)*gt[2];
337  y=gt[3]+(0.5+i)*gt[4]+(0.5+j)*gt[5];
338  if(isGeoRef()){
339  // x=m_ulx+(0.5+i)*m_delta_x;
340  // y=m_uly-(0.5+j)*m_delta_y;
341  return true;
342  }
343  else{
344  // x=0.5+i;
345  // y=nrOfRow()-(0.5+j);
346  return false;
347  }
348 }
349 
350 bool ImgReaderGdal::covers(double x, double y) const
351 {
352  double theULX, theULY, theLRX, theLRY;
353  getBoundingBox(theULX,theULY,theLRX,theLRY);
354  return((x > theULX)&&
355  (x < theLRX)&&
356  (y < theULY)&&
357  (y >theLRY));
358 }
359 
360 bool ImgReaderGdal::covers(double ulx, double uly, double lrx, double lry) const
361 {
362  double theULX, theULY, theLRX, theLRY;
363  getBoundingBox(theULX,theULY,theLRX,theLRY);
364  return((ulx < theLRX)&&(lrx > theULX)&&(lry < theULY)&&(uly > theLRY));
365 }
366 
367 double ImgReaderGdal::getMin(int& x, int& y, int band) const{
368  double minValue=0;
369  std::vector<double> lineBuffer(nrOfCol());
370  bool init=false;
371  for(int irow=0;irow<nrOfRow();++irow){
372  readData(lineBuffer,GDT_Float64,irow,band);
373  for(int icol=0;icol<nrOfCol();++icol){
374  // bool valid=(find(m_noDataValues.begin(),m_noDataValues.end(),lineBuffer[icol])==m_noDataValues.end());
375  if(!isNoData(lineBuffer[icol])){
376  if(!init){
377  y=irow;
378  x=icol;
379  minValue=lineBuffer[icol];
380  init=true;
381  }
382  else if(minValue>lineBuffer[icol]){
383  y=irow;
384  x=icol;
385  minValue=lineBuffer[icol];
386  }
387  }
388  }
389  }
390  if(init)
391  return minValue;
392  else
393  throw(static_cast<std::string>("Warning: not initialized"));
394 }
395 
396 double ImgReaderGdal::getMax(int& x, int& y, int band) const{
397  double maxValue=0;
398  std::vector<double> lineBuffer(nrOfCol());
399  bool init=false;
400  for(int irow=0;irow<nrOfRow();++irow){
401  readData(lineBuffer,GDT_Float64,irow,band);
402  for(int icol=0;icol<nrOfCol();++icol){
403  // bool valid=(find(m_noDataValues.begin(),m_noDataValues.end(),lineBuffer[icol])==m_noDataValues.end());
404  // if(valid){
405  if(!isNoData(lineBuffer[icol])){
406  if(!init){
407  y=irow;
408  x=icol;
409  maxValue=lineBuffer[icol];
410  init=true;
411  }
412  else if(maxValue<lineBuffer[icol]){
413  y=irow;
414  x=icol;
415  maxValue=lineBuffer[icol];
416  }
417  }
418  }
419  }
420  if(init)
421  return maxValue;
422  else
423  throw(static_cast<std::string>("Warning: not initialized"));
424 }
425 
426 void ImgReaderGdal::getMinMax(int startCol, int endCol, int startRow, int endRow, int band, double& minValue, double& maxValue) const
427 {
428  // GDALRasterBand *poBand;
429  // int bGotMin, bGotMax;
430  // double adfMinMax[2];
431 
432  // poBand = m_gds->GetRasterBand(band+1);
433  // adfMinMax[0] = poBand->GetMinimum( &bGotMin );
434  // adfMinMax[1] = poBand->GetMaximum( &bGotMax );
435  // if( ! (bGotMin && bGotMax) )
436  // GDALComputeRasterMinMax((GDALRasterBandH)poBand, FALSE, adfMinMax);
437  // // GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
438  // minValue=adfMinMax[0];
439  // maxValue=adfMinMax[1];
440 
441  std::vector<double> lineBuffer(endCol-startCol+1);
442  bool init=false;
443  assert(endRow<nrOfRow());
444  for(int irow=startCol;irow<endRow+1;++irow){
445  readData(lineBuffer,GDT_Float64,startCol,endCol,irow,band);
446  for(int icol=0;icol<lineBuffer.size();++icol){
447  if(!isNoData(lineBuffer[icol])){
448  if(!init){
449  minValue=lineBuffer[icol];
450  maxValue=lineBuffer[icol];
451  init=true;
452  }
453  else{
454  if(minValue>lineBuffer[icol])
455  minValue=lineBuffer[icol];
456  if(maxValue<lineBuffer[icol])
457  maxValue=lineBuffer[icol];
458  }
459  }
460  }
461  }
462  if(!init)
463  throw(static_cast<std::string>("Warning: not initialized"));
464 }
465 
466 void ImgReaderGdal::getMinMax(double& minValue, double& maxValue, int band, bool exhaustiveSearch) const
467 {
468  if(exhaustiveSearch){//force exhaustive search
469  std::vector<double> lineBuffer(nrOfCol());
470  bool init=false;
471  for(int irow=0;irow<nrOfRow();++irow){
472  readData(lineBuffer,GDT_Float64,irow,band);
473  for(int icol=0;icol<nrOfCol();++icol){
474  // bool valid=(find(m_noDataValues.begin(),m_noDataValues.end(),lineBuffer[icol])==m_noDataValues.end());
475  // if(valid){
476  if(!isNoData(lineBuffer[icol])){
477  if(!init){
478  minValue=lineBuffer[icol];
479  maxValue=lineBuffer[icol];
480  init=true;
481  }
482  else{
483  if(minValue>lineBuffer[icol])
484  minValue=lineBuffer[icol];
485  if(maxValue<lineBuffer[icol])
486  maxValue=lineBuffer[icol];
487  }
488  }
489  }
490  }
491  if(!init)
492  throw(static_cast<std::string>("Warning: not initialized"));
493  }
494  else{
495  GDALRasterBand *poBand;
496  int bGotMin, bGotMax;
497  double adfMinMax[2];
498 
499  poBand = m_gds->GetRasterBand(band+1);
500  adfMinMax[0] = poBand->GetMinimum( &bGotMin );
501  adfMinMax[1] = poBand->GetMaximum( &bGotMax );
502  if( ! (bGotMin && bGotMax) )
503  GDALComputeRasterMinMax((GDALRasterBandH)poBand, FALSE, adfMinMax);
504  minValue=adfMinMax[0];
505  maxValue=adfMinMax[1];
506  if(m_scale.size()>band){
507  minValue*=m_scale[band];
508  maxValue*=m_scale[band];
509  }
510  if(m_offset.size()>band){
511  minValue+=m_offset[band];
512  maxValue+=m_offset[band];
513  }
514  }
515 }
516 
517 double ImgReaderGdal::getHistogram(std::vector<double>& histvector, double& min, double& max, unsigned int& nbin, int theBand, bool kde){
518  double minValue=0;
519  double maxValue=0;
520 
521  if(min>=max)
522  getMinMax(minValue,maxValue,theBand);
523  else{
524  minValue=min;
525  maxValue=max;
526  }
527  if(min<max&&min>minValue)
528  minValue=min;
529  if(min<max&&max<maxValue)
530  maxValue=max;
531  min=minValue;
532  max=maxValue;
533 
534  double sigma=0;
535  if(kde){
536  double meanValue=0;
537  double stdDev=0;
538  GDALProgressFunc pfnProgress;
539  void* pProgressData;
540  GDALRasterBand* rasterBand;
541  rasterBand=getRasterBand(theBand);
542  rasterBand->ComputeStatistics(0,&minValue,&maxValue,&meanValue,&stdDev,pfnProgress,pProgressData);
543  //rest minvalue and MaxValue as ComputeStatistics does not account for nodata, scale and offset
544  minValue=min;
545  maxValue=max;
546 
547  if(m_scale.size()>theBand){
548  stdDev*=m_scale[theBand];
549  }
550  sigma=1.06*stdDev*pow(getNvalid(theBand),-0.2);
551  }
552 
553  double scale=0;
554  if(maxValue>minValue){
555  if(nbin==0)
556  nbin=maxValue-minValue+1;
557  scale=static_cast<double>(nbin-1)/(maxValue-minValue);
558  }
559  else
560  nbin=1;
561  assert(nbin>0);
562  if(histvector.size()!=nbin){
563  histvector.resize(nbin);
564  for(int i=0;i<nbin;histvector[i++]=0);
565  }
566  double nvalid=0;
567  unsigned long int nsample=0;
568  unsigned long int ninvalid=0;
569  std::vector<double> lineBuffer(nrOfCol());
570  for(int irow=0;irow<nrOfRow();++irow){
571  readData(lineBuffer,GDT_Float64,irow,theBand);
572  for(int icol=0;icol<nrOfCol();++icol){
573  if(isNoData(lineBuffer[icol]))
574  ++ninvalid;
575  else if(lineBuffer[icol]>maxValue)
576  ++ninvalid;
577  else if(lineBuffer[icol]<minValue)
578  ++ninvalid;
579  else if(nbin==1)
580  ++histvector[0];
581  else{//scale to [0:nbin]
582  if(sigma>0){
583  //create kde for Gaussian basis function
584  //todo: speed up by calculating first and last bin with non-zero contriubtion...
585  //todo: calculate real surface below pdf by using gsl_cdf_gaussian_P(x-mean+binsize,sigma)-gsl_cdf_gaussian_P(x-mean,sigma)
586  //hiero
587  for(int ibin=0;ibin<nbin;++ibin){
588  double icenter=minValue+static_cast<double>(maxValue-minValue)*(ibin+0.5)/nbin;
589  double thePdf=gsl_ran_gaussian_pdf(lineBuffer[icol]-icenter, sigma);
590  histvector[ibin]+=thePdf;
591  nvalid+=thePdf;
592  }
593  }
594  else{
595  int theBin=static_cast<unsigned long int>(scale*(lineBuffer[icol]-minValue));
596  assert(theBin>=0);
597  assert(theBin<nbin);
598  ++histvector[theBin];
599  ++nvalid;
600  }
601  // else if(lineBuffer[icol]==maxValue)
602  // ++histvector[nbin-1];
603  // else
604  // ++histvector[static_cast<int>(static_cast<double>(lineBuffer[icol]-minValue)/(maxValue-minValue)*(nbin-1))];
605  }
606  }
607  }
608  // unsigned long int nvalid=nrOfCol()*nrOfRow()-ninvalid;
609  return nvalid;
610 }
611 
612 void ImgReaderGdal::getRange(std::vector<short>& range, int band) const
613 {
614  std::vector<short> lineBuffer(nrOfCol());
615  range.clear();
616  for(int irow=0;irow<nrOfRow();++irow){
617  readData(lineBuffer,GDT_Int16,irow,band);
618  for(int icol=0;icol<nrOfCol();++icol){
619  if(find(range.begin(),range.end(),lineBuffer[icol])==range.end())
620  range.push_back(lineBuffer[icol]);
621  }
622  }
623  sort(range.begin(),range.end());
624 }
625 
626 unsigned long int ImgReaderGdal::getNvalid(int band) const
627 {
628  unsigned long int nvalid=0;
629  if(m_noDataValues.size()){
630  std::vector<double> lineBuffer(nrOfCol());
631  for(int irow=0;irow<nrOfRow();++irow){
632  readData(lineBuffer,GDT_Float64,irow,band);
633  for(int icol=0;icol<nrOfCol();++icol){
634  if(isNoData(lineBuffer[icol]))
635  continue;
636  else
637  ++nvalid;
638  }
639  }
640  return nvalid;
641  }
642  else
643  return(nrOfCol()*nrOfRow());
644 }
645 
646 int ImgReaderGdal::getNoDataValues(std::vector<double>& noDataValues) const
647 {
648  if(m_noDataValues.size()){
649  noDataValues=m_noDataValues;
650  return m_noDataValues.size();
651  }
652  else
653  return 0;
654 }
655 
656 int ImgReaderGdal::pushNoDataValue(double noDataValue)
657 {
658  if(find(m_noDataValues.begin(),m_noDataValues.end(),noDataValue)==m_noDataValues.end())
659  m_noDataValues.push_back(noDataValue);
660  return(m_noDataValues.size());
661 }
662 
663 // bool ImgReaderGdal::setNoDataValue(double noDataValue,int band)
664 // {
665 // GDALRasterBand *poBand;
666 // poBand = m_gds->GetRasterBand(band+1);
667 // if(poBand->SetNoDataValue(noDataValue)!=CE_None)
668 // return false;
669 // else
670 // return true;
671 // }
672 
673 void ImgReaderGdal::getRefPix(double& refX, double &refY, int band) const
674 {
675  std::vector<double> lineBuffer(nrOfCol());
676  double validCol=0;
677  double validRow=0;
678  int nvalidCol=0;
679  int nvalidRow=0;
680  for(int irow=0;irow<nrOfRow();++irow){
681  readData(lineBuffer,GDT_Float64,irow,band);
682  for(int icol=0;icol<nrOfCol();++icol){
683  // bool valid=(find(m_noDataValues.begin(),m_noDataValues.end(),lineBuffer[icol])==m_noDataValues.end());
684  // if(valid){
685  if(!isNoData(lineBuffer[icol])){
686  validCol+=icol+1;
687  ++nvalidCol;
688  validRow+=irow+1;
689  ++nvalidRow;
690  }
691  }
692  }
693  if(isGeoRef()){
694  //reference coordinate is lower left corner of pixel in center of gravity
695  //we need geo coordinates for exactly this location: validCol(Row)/nvalidCol(Row)-0.5
696  double cgravi=validCol/nvalidCol-0.5;
697  double cgravj=validRow/nvalidRow-0.5;
698  double refpixeli=floor(cgravi);
699  double refpixelj=ceil(cgravj-1);
700  //but image2geo provides location at center of pixel (shifted half pixel right down)
701  image2geo(refpixeli,refpixelj,refX,refY);
702  //refX and refY now refer to center of gravity pixel
703  refX-=0.5*getDeltaX();//shift to left corner
704  refY-=0.5*getDeltaY();//shift to lower left corner
705  }
706  else{
707  refX=floor(validCol/nvalidCol-0.5);//left corner
708  refY=floor(validRow/nvalidRow-0.5);//upper corner
709  //shift to lower left corner of pixel
710  refY+=1;
711 
712  }
713 }