pktools  2.6.6
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 
28 ImgReaderGdal::~ImgReaderGdal(void)
29 {
30  // delete m_gds;
31 // GDALDumpOpenDatasets(stderr);
32 // GDALDestroyDriverManager();//could be used by other objects...
33 }
34 
35 //--------------------------------------------------------------------------
36 void ImgReaderGdal::open(const std::string& filename, const GDALAccess& readMode)
37 {
38  m_filename = filename;
39  setCodec(readMode);
40 }
41 
42 void ImgReaderGdal::close(void)
43 {
44  ImgRasterGdal::close();
45 }
46 
47 void ImgReaderGdal::setCodec(const GDALAccess& readMode)
48 {
49  GDALAllRegister();
50  m_gds = (GDALDataset *) GDALOpen(m_filename.c_str(), readMode );
51  if(m_gds == NULL){
52  std::string errorString="FileOpenError";
53  throw(errorString);
54  }
55  m_ncol= m_gds->GetRasterXSize();
56  m_nrow= m_gds->GetRasterYSize();
57  m_nband= m_gds->GetRasterCount();
58  // m_isGeoRef=( static_cast<std::string>(m_gds->GetProjectionRef()) != "" );
59  // m_magic_x=magicX;
60  // m_magic_y=magicY;
61  double adfGeoTransform[6];
62  m_gds->GetGeoTransform( adfGeoTransform );
63  // if( m_gds->GetGeoTransform( adfGeoTransform ) == CE_None ){
64  m_gt[0]=adfGeoTransform[0];
65  m_gt[1]=adfGeoTransform[1];
66  m_gt[2]=adfGeoTransform[2];
67  m_gt[3]=adfGeoTransform[3];
68  m_gt[4]=adfGeoTransform[4];
69  m_gt[5]=adfGeoTransform[5];
70  // }
71  // else{
72  // m_gt[0]=0;
73  // m_gt[1]=1;
74  // m_gt[2]=0;
75  // m_gt[3]=0;
76  // m_gt[4]=0;
77  // m_gt[5]=1;
78  // }
79 }
80 
81 
82 double ImgReaderGdal::getMin(int& x, int& y, int band) const{
83  double minValue=0;
84  std::vector<double> lineBuffer(nrOfCol());
85  bool isValid=false;
86  for(int irow=0;irow<nrOfRow();++irow){
87  readData(lineBuffer,GDT_Float64,irow,band);
88  for(int icol=0;icol<nrOfCol();++icol){
89  if(isNoData(lineBuffer[icol]))
90  continue;
91  if(isValid){
92  if(lineBuffer[icol]<minValue){
93  y=irow;
94  x=icol;
95  minValue=lineBuffer[icol];
96  }
97  }
98  else{
99  y=irow;
100  x=icol;
101  minValue=lineBuffer[icol];
102  isValid=true;
103  }
104  }
105  }
106  if(isValid)
107  return minValue;
108  else
109  throw(static_cast<std::string>("Warning: not initialized"));
110 }
111 
112 double ImgReaderGdal::getMax(int& x, int& y, int band) const{
113  double maxValue=0;
114  std::vector<double> lineBuffer(nrOfCol());
115  bool isValid=false;
116  for(int irow=0;irow<nrOfRow();++irow){
117  readData(lineBuffer,GDT_Float64,irow,band);
118  for(int icol=0;icol<nrOfCol();++icol){
119  if(isNoData(lineBuffer[icol]))
120  continue;
121  if(isValid){
122  if(lineBuffer[icol]>maxValue){
123  y=irow;
124  x=icol;
125  maxValue=lineBuffer[icol];
126  }
127  }
128  else{
129  y=irow;
130  x=icol;
131  maxValue=lineBuffer[icol];
132  isValid=true;
133  }
134  }
135  }
136  if(isValid)
137  return maxValue;
138  else
139  throw(static_cast<std::string>("Warning: not initialized"));
140 }
141 
142 void ImgReaderGdal::getMinMax(int startCol, int endCol, int startRow, int endRow, int band, double& minValue, double& maxValue) const
143 {
144  bool isConstraint=(maxValue>minValue);
145  double minConstraint=minValue;
146  double maxConstraint=maxValue;
147  std::vector<double> lineBuffer(endCol-startCol+1);
148  bool isValid=false;
149  assert(endRow<nrOfRow());
150  for(int irow=startCol;irow<endRow+1;++irow){
151  readData(lineBuffer,GDT_Float64,startCol,endCol,irow,band);
152  for(int icol=0;icol<lineBuffer.size();++icol){
153  if(isNoData(lineBuffer[icol]))
154  continue;
155  if(isValid){
156  if(isConstraint){
157  if(lineBuffer[icol]<minConstraint)
158  continue;
159  if(lineBuffer[icol]>maxConstraint)
160  continue;
161  }
162  if(lineBuffer[icol]<minValue)
163  minValue=lineBuffer[icol];
164  if(lineBuffer[icol]>maxValue)
165  maxValue=lineBuffer[icol];
166  }
167  else{
168  if(isConstraint){
169  if(lineBuffer[icol]<minConstraint)
170  continue;
171  if(lineBuffer[icol]>maxConstraint)
172  continue;
173  }
174  minValue=lineBuffer[icol];
175  maxValue=lineBuffer[icol];
176  isValid=true;
177  }
178  }
179  }
180  if(!isValid)
181  throw(static_cast<std::string>("Warning: not initialized"));
182 }
183 
184 void ImgReaderGdal::getMinMax(double& minValue, double& maxValue, int band) const
185 {
186  bool isConstraint=(maxValue>minValue);
187  double minConstraint=minValue;
188  double maxConstraint=maxValue;
189  std::vector<double> lineBuffer(nrOfCol());
190  bool isValid=false;
191  for(int irow=0;irow<nrOfRow();++irow){
192  readData(lineBuffer,GDT_Float64,irow,band);
193  for(int icol=0;icol<nrOfCol();++icol){
194  if(isNoData(lineBuffer[icol]))
195  continue;
196  if(isValid){
197  if(isConstraint){
198  if(lineBuffer[icol]<minConstraint)
199  continue;
200  if(lineBuffer[icol]>maxConstraint)
201  continue;
202  }
203  if(lineBuffer[icol]<minValue)
204  minValue=lineBuffer[icol];
205  if(lineBuffer[icol]>maxValue)
206  maxValue=lineBuffer[icol];
207  }
208  else{
209  if(isConstraint){
210  if(lineBuffer[icol]<minConstraint)
211  continue;
212  if(lineBuffer[icol]>maxConstraint)
213  continue;
214  }
215  minValue=lineBuffer[icol];
216  maxValue=lineBuffer[icol];
217  isValid=true;
218  }
219  }
220  }
221  if(!isValid)
222  throw(static_cast<std::string>("Warning: not initialized"));
223 }
224 
225 double ImgReaderGdal::getHistogram(std::vector<double>& histvector, double& min, double& max, unsigned int& nbin, int theBand, bool kde){
226  double minValue=0;
227  double maxValue=0;
228 
229  if(min>=max)
230  getMinMax(minValue,maxValue,theBand);
231  else{
232  minValue=min;
233  maxValue=max;
234  }
235  if(min<max&&min>minValue)
236  minValue=min;
237  if(min<max&&max<maxValue)
238  maxValue=max;
239  min=minValue;
240  max=maxValue;
241 
242  double sigma=0;
243  if(kde){
244  double meanValue=0;
245  double stdDev=0;
246  GDALProgressFunc pfnProgress;
247  void* pProgressData;
248  GDALRasterBand* rasterBand;
249  rasterBand=getRasterBand(theBand);
250  rasterBand->ComputeStatistics(0,&minValue,&maxValue,&meanValue,&stdDev,pfnProgress,pProgressData);
251  //rest minvalue and MaxValue as ComputeStatistics does not account for nodata, scale and offset
252  minValue=min;
253  maxValue=max;
254 
255  if(m_scale.size()>theBand){
256  stdDev*=m_scale[theBand];
257  }
258  sigma=1.06*stdDev*pow(getNvalid(theBand),-0.2);
259  }
260 
261  double scale=0;
262  if(maxValue>minValue){
263  if(nbin==0)
264  nbin=maxValue-minValue+1;
265  scale=static_cast<double>(nbin-1)/(maxValue-minValue);
266  }
267  else
268  nbin=1;
269  assert(nbin>0);
270  if(histvector.size()!=nbin){
271  histvector.resize(nbin);
272  for(int i=0;i<nbin;histvector[i++]=0);
273  }
274  double nvalid=0;
275  unsigned long int nsample=0;
276  unsigned long int ninvalid=0;
277  std::vector<double> lineBuffer(nrOfCol());
278  for(int irow=0;irow<nrOfRow();++irow){
279  readData(lineBuffer,GDT_Float64,irow,theBand);
280  for(int icol=0;icol<nrOfCol();++icol){
281  if(isNoData(lineBuffer[icol]))
282  ++ninvalid;
283  else if(lineBuffer[icol]>maxValue)
284  ++ninvalid;
285  else if(lineBuffer[icol]<minValue)
286  ++ninvalid;
287  else if(nbin==1)
288  ++histvector[0];
289  else{//scale to [0:nbin]
290  if(sigma>0){
291  //create kde for Gaussian basis function
292  //todo: speed up by calculating first and last bin with non-zero contriubtion...
293  //todo: calculate real surface below pdf by using gsl_cdf_gaussian_P(x-mean+binsize,sigma)-gsl_cdf_gaussian_P(x-mean,sigma)
294  //hiero
295  for(int ibin=0;ibin<nbin;++ibin){
296  double icenter=minValue+static_cast<double>(maxValue-minValue)*(ibin+0.5)/nbin;
297  double thePdf=gsl_ran_gaussian_pdf(lineBuffer[icol]-icenter, sigma);
298  histvector[ibin]+=thePdf;
299  nvalid+=thePdf;
300  }
301  }
302  else{
303  int theBin=static_cast<unsigned long int>(scale*(lineBuffer[icol]-minValue));
304  assert(theBin>=0);
305  assert(theBin<nbin);
306  ++histvector[theBin];
307  ++nvalid;
308  }
309  // else if(lineBuffer[icol]==maxValue)
310  // ++histvector[nbin-1];
311  // else
312  // ++histvector[static_cast<int>(static_cast<double>(lineBuffer[icol]-minValue)/(maxValue-minValue)*(nbin-1))];
313  }
314  }
315  }
316  // unsigned long int nvalid=nrOfCol()*nrOfRow()-ninvalid;
317  return nvalid;
318 }
319 
320 void ImgReaderGdal::getRange(std::vector<short>& range, int band) const
321 {
322  std::vector<short> lineBuffer(nrOfCol());
323  range.clear();
324  for(int irow=0;irow<nrOfRow();++irow){
325  readData(lineBuffer,GDT_Int16,irow,band);
326  for(int icol=0;icol<nrOfCol();++icol){
327  if(find(range.begin(),range.end(),lineBuffer[icol])==range.end())
328  range.push_back(lineBuffer[icol]);
329  }
330  }
331  sort(range.begin(),range.end());
332 }
333 
334 unsigned long int ImgReaderGdal::getNvalid(int band) const
335 {
336  unsigned long int nvalid=0;
337  if(m_noDataValues.size()){
338  std::vector<double> lineBuffer(nrOfCol());
339  for(int irow=0;irow<nrOfRow();++irow){
340  readData(lineBuffer,GDT_Float64,irow,band);
341  for(int icol=0;icol<nrOfCol();++icol){
342  if(isNoData(lineBuffer[icol]))
343  continue;
344  else
345  ++nvalid;
346  }
347  }
348  return nvalid;
349  }
350  else
351  return(nrOfCol()*nrOfRow());
352 }
353 
354 
355 void ImgReaderGdal::getRefPix(double& refX, double &refY, int band) const
356 {
357  std::vector<double> lineBuffer(nrOfCol());
358  double validCol=0;
359  double validRow=0;
360  int nvalidCol=0;
361  int nvalidRow=0;
362  for(int irow=0;irow<nrOfRow();++irow){
363  readData(lineBuffer,GDT_Float64,irow,band);
364  for(int icol=0;icol<nrOfCol();++icol){
365  // bool valid=(find(m_noDataValues.begin(),m_noDataValues.end(),lineBuffer[icol])==m_noDataValues.end());
366  // if(valid){
367  if(!isNoData(lineBuffer[icol])){
368  validCol+=icol+1;
369  ++nvalidCol;
370  validRow+=irow+1;
371  ++nvalidRow;
372  }
373  }
374  }
375  if(isGeoRef()){
376  //reference coordinate is lower left corner of pixel in center of gravity
377  //we need geo coordinates for exactly this location: validCol(Row)/nvalidCol(Row)-0.5
378  double cgravi=validCol/nvalidCol-0.5;
379  double cgravj=validRow/nvalidRow-0.5;
380  double refpixeli=floor(cgravi);
381  double refpixelj=ceil(cgravj-1);
382  //but image2geo provides location at center of pixel (shifted half pixel right down)
383  image2geo(refpixeli,refpixelj,refX,refY);
384  //refX and refY now refer to center of gravity pixel
385  refX-=0.5*getDeltaX();//shift to left corner
386  refY-=0.5*getDeltaY();//shift to lower left corner
387  }
388  else{
389  refX=floor(validCol/nvalidCol-0.5);//left corner
390  refY=floor(validRow/nvalidRow-0.5);//upper corner
391  //shift to lower left corner of pixel
392  refY+=1;
393 
394  }
395 }