pktools  2.6.3
Processing Kernel for geospatial data
pkdumpimg.cc
1 /**********************************************************************
2 pkdumpimg.cc: program to dump image content to ascii or std out
3 Copyright (C) 2008-2014 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 <string>
21 #include <fstream>
22 #include <vector>
23 #include <iostream>
24 #include <assert.h>
25 #include "base/Optionpk.h"
26 #include "imageclasses/ImgReaderOgr.h"
27 #include "imageclasses/ImgWriterGdal.h"
28 // #include "imageclasses/ImgWriterOgr.h"
29 
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33 
34 using namespace std;
35 
36 int main(int argc, char *argv[])
37 {
38  Optionpk<std::string> input_opt("i","input","input image file","");
39  Optionpk<string> output_opt("o", "output", "Output ascii file (Default is empty: use stdout", "");
40  Optionpk<string> oformat_opt("of", "oformat", "Output format (matrix form or list (x,y,z) form. Default is matrix form", "matrix");
41  Optionpk<int> band_opt("b", "band", "band index to crop");
42  Optionpk<string> extent_opt("e", "extent", "get boundary from extent from polygons in vector file", "");
43  Optionpk<double> ulx_opt("ulx", "ulx", "Upper left x value bounding box (in geocoordinates if georef is true)",0.0);
44  Optionpk<double> uly_opt("uly", "uly", "Upper left y value bounding box (in geocoordinates if georef is true)",0.0);
45  Optionpk<double> lrx_opt("lrx", "lrx", "Lower left x value bounding box (in geocoordinates if georef is true)",0.0);
46  Optionpk<double> lry_opt("lry", "lry", "Lower left y value bounding box (in geocoordinates if georef is true)",0.0);
47  Optionpk<double> dx_opt("dx", "dx", "Output resolution in x (in meter) (0.0: keep original resolution)",0.0);
48  Optionpk<double> dy_opt("dy", "dy", "Output resolution in y (in meter) (0.0: keep original resolution)",0.0);
49  Optionpk<string> resample_opt("r", "resampling-method", "Resampling method (near: nearest neighbour, bilinear: bi-linear interpolation).", "near");
50  Optionpk<short> dstnodata_opt("dstnodata", "dstnodata", "nodata value for output if out of bounds.", 0);
51  Optionpk<double> srcnodata_opt("srcnodata", "srcnodata", "set no data value(s) for input image");
52  Optionpk<short> verbose_opt("v", "verbose", "verbose (Default: 0)", 0,2);
53 
54  dx_opt.setHide(1);
55  dy_opt.setHide(1);
56  resample_opt.setHide(1);
57  srcnodata_opt.setHide(1);
58  dstnodata_opt.setHide(1);
59 
60  bool doProcess;//stop process when program was invoked with help option (-h --help)
61  try{
62  doProcess=input_opt.retrieveOption(argc,argv);
63  output_opt.retrieveOption(argc,argv);
64  oformat_opt.retrieveOption(argc,argv);
65  band_opt.retrieveOption(argc,argv);
66  extent_opt.retrieveOption(argc,argv);
67  ulx_opt.retrieveOption(argc,argv);
68  uly_opt.retrieveOption(argc,argv);
69  lrx_opt.retrieveOption(argc,argv);
70  lry_opt.retrieveOption(argc,argv);
71  dx_opt.retrieveOption(argc,argv);
72  dy_opt.retrieveOption(argc,argv);
73  resample_opt.retrieveOption(argc,argv);
74  srcnodata_opt.retrieveOption(argc,argv);
75  dstnodata_opt.retrieveOption(argc,argv);
76  verbose_opt.retrieveOption(argc,argv);
77  }
78  catch(string predefinedString){
79  std::cout << predefinedString << std::endl;
80  exit(0);
81  }
82  if(!doProcess){
83  cout << endl;
84  cout << "Usage: pkdumpimg -i input.txt [-o output]" << endl;
85  cout << endl;
86  std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
87  exit(0);//help was invoked, stop processing
88  }
89 
90  ofstream outputStream;
91  if(!output_opt.empty())
92  outputStream.open(output_opt[0].c_str());
93 
94  RESAMPLE theResample;
95  if(resample_opt[0]=="near"){
96  theResample=NEAR;
97  if(verbose_opt[0])
98  cout << "resampling: nearest neighbour" << endl;
99  }
100  else if(resample_opt[0]=="bilinear"){
101  theResample=BILINEAR;
102  if(verbose_opt[0])
103  cout << "resampling: bilinear interpolation" << endl;
104  }
105  else{
106  std::cout << "Error: resampling method " << resample_opt[0] << " not supported" << std::endl;
107  exit(1);
108  }
109 
110  // ImgWriterGdal imgWriter;
111  GDALDataType theType;
112 
113  if(input_opt.empty()){
114  std::cerr << "No input file provided (use option -i). Use --help for help information" << std::endl;
115  exit(0);
116  }
117 
118  ImgReaderGdal imgReader(input_opt[0]);
119  for(int inodata=0;inodata<srcnodata_opt.size();++inodata)
120  imgReader.pushNoDataValue(srcnodata_opt[inodata]);
121 
122  // ImgWriterGdal virtualWriter;//only for coordinate conversion (no output file defined)
123 
124  int nband=imgReader.nrOfBand();
125  //get number of lines
126  int nrow=imgReader.nrOfRow();
127  int ncol=imgReader.nrOfCol();
128  int ncropcol=0;
129  int ncroprow=0;
130  double dx=dx_opt[0];
131  double dy=dy_opt[0];
132  if(!dx||!dy){
133  dx=imgReader.getDeltaX();
134  dy=imgReader.getDeltaY();
135  }
136  //bounding box of cropped image
137  double cropulx=ulx_opt[0];
138  double cropuly=uly_opt[0];
139  double croplrx=lrx_opt[0];
140  double croplry=lry_opt[0];
141  //get bounding box from extentReader if defined
142  ImgReaderOgr extentReader;
143  if(extent_opt[0]!=""){
144  for(int iextent=0;iextent<extent_opt.size();++iextent){
145  extentReader.open(extent_opt[iextent]);
146  if(!(extentReader.getExtent(ulx_opt[0],uly_opt[0],lrx_opt[0],lry_opt[0]))){
147  cerr << "Error: could not get extent from " << extent_opt[0] << endl;
148  exit(1);
149  }
150  if(!iextent){
151  cropulx=ulx_opt[0];
152  cropuly=uly_opt[0];
153  croplry=lry_opt[0];
154  croplrx=lrx_opt[0];
155  }
156  else{
157  if(ulx_opt[0]<cropulx)
158  cropulx=ulx_opt[0];
159  if(uly_opt[0]>cropuly)
160  cropuly=uly_opt[0];
161  if(lry_opt[0]<croplry)
162  croplry=lry_opt[0];
163  if(lrx_opt[0]>croplrx)
164  croplrx=lrx_opt[0];
165  }
166  extentReader.close();
167  }
168  }
169  double uli,ulj,lri,lrj;//image coordinates
170  double magicX=1,magicY=1;
171  if(ulx_opt[0]>=lrx_opt[0]){//default bounding box: no cropping
172  uli=0;
173  lri=imgReader.nrOfCol()-1;
174  ulj=0;
175  lrj=imgReader.nrOfRow()-1;
176  ncropcol=imgReader.nrOfCol();
177  ncroprow=imgReader.nrOfRow();
178  imgReader.getBoundingBox(cropulx,cropuly,croplrx,croplry);
179  imgReader.geo2image(cropulx+(magicX-1.0)*imgReader.getDeltaX(),cropuly-(magicY-1.0)*imgReader.getDeltaY(),uli,ulj);
180  imgReader.geo2image(croplrx+(magicX-2.0)*imgReader.getDeltaX(),croplry-(magicY-2.0)*imgReader.getDeltaY(),lri,lrj);
181  ncropcol=abs(static_cast<int>(ceil((croplrx-cropulx)/dx)));
182  ncroprow=abs(static_cast<int>(ceil((cropuly-croplry)/dy)));
183  }
184  else{
185  imgReader.geo2image(cropulx+(magicX-1.0)*imgReader.getDeltaX(),cropuly-(magicY-1.0)*imgReader.getDeltaY(),uli,ulj);
186  imgReader.geo2image(croplrx+(magicX-2.0)*imgReader.getDeltaX(),croplry-(magicY-2.0)*imgReader.getDeltaY(),lri,lrj);
187 
188  ncropcol=abs(static_cast<int>(ceil((croplrx-cropulx)/dx)));
189  ncroprow=abs(static_cast<int>(ceil((cropuly-croplry)/dy)));
190  uli=floor(uli);
191  ulj=floor(ulj);
192  lri=floor(lri);
193  lrj=floor(lrj);
194  }
195  double startCol=uli;
196  double endCol=lri;
197  double dcropcol=0;
198  double dcroprow=0;
199  double deltaX=imgReader.getDeltaX();
200  double deltaY=imgReader.getDeltaY();
201  dcropcol=(lri-uli+1)/(dx/deltaX);
202  dcroprow=(lrj-ulj+1)/(dy/deltaY);
203  if(verbose_opt[0]){
204  cout << "cropulx: " << cropulx << endl;
205  cout << "cropuly: " << cropuly << endl;
206  cout << "croplrx: " << croplrx << endl;
207  cout << "croplry: " << croplry << endl;
208  cout << "ncropcol: " << ncropcol << endl;
209  cout << "ncroprow: " << ncroprow << endl;
210  cout << "cropulx+ncropcol*dx: " << cropulx+ncropcol*dx << endl;
211  cout << "cropuly-ncroprow*dy: " << cropuly-ncroprow*dy << endl;
212  cout << "selected upper left column in input image: " << uli << endl;
213  cout << "selected upper left row of input image: " << ulj << endl;
214  cout << "selected lower right column in input image: " << lri << endl;
215  cout << "selected lower right row in input image: " << lrj << endl;
216  }
217  double gt[6];
218  imgReader.getGeoTransform(gt);
219  // imgWriter.setGeoTransform(gt);
220  // imgWriter.setProjection(imgReader.getProjection());
221 
222  double readRow=0;
223  double readCol=0;
224  double lowerCol=0;
225  double upperCol=0;
226  int readncol=endCol-startCol+1;
227  //test
228  // vector<double> readBuffer(readncol);
229  vector<double> readBuffer(readncol+1);
230  // assert(imgWriter.isGeoRef());
231  if(band_opt.empty()){
232  for(int iband=0;iband<imgReader.nrOfBand();++iband)
233  band_opt.push_back(iband);
234  }
235  for(int iband=0;iband<band_opt.size();++iband){
236  assert(band_opt[iband]>=0);
237  assert(band_opt[iband]<imgReader.nrOfBand());
238  for(int irow=0;irow<ncroprow;++irow){
239  if(verbose_opt[0])
240  std::cout << irow << std::endl;
241  double x=0;
242  double y=0;
243  //convert irow to geo
244  // imgWriter.image2geo(0,irow,x,y);
245  imgReader.image2geo(0,irow,x,y);
246  //lookup corresponding row for irow in this file
247  imgReader.geo2image(x,y,readCol,readRow);
248  if(readRow<0||readRow>=imgReader.nrOfRow()){
249  if(verbose_opt[0]>1)
250  std::cout << "skipping row " << readRow << std::endl;
251  continue;
252  }
253  try{
254  //test
255  // imgReader.readData(readBuffer,GDT_Float64,startCol,endCol,readRow,band_opt[0],theResample);
256  if(endCol<imgReader.nrOfCol()-1)
257  imgReader.readData(readBuffer,GDT_Float64,startCol,endCol+1,readRow,band_opt[iband],theResample);
258  else
259  imgReader.readData(readBuffer,GDT_Float64,startCol,endCol,readRow,band_opt[iband],theResample);
260  for(int ib=0;ib<ncropcol;++ib){
261  // assert(imgWriter.image2geo(ib,irow,x,y));
262  assert(imgReader.image2geo(ib,irow,x,y));
263  //lookup corresponding row for irow in this file
264  imgReader.geo2image(x,y,readCol,readRow);
265  if(readCol<0||readCol>=imgReader.nrOfCol()){
266  if(oformat_opt[0]=="matrix"){
267  if(output_opt[0].empty())
268  std::cout << dstnodata_opt[0] << " ";
269  else
270  outputStream << dstnodata_opt[0] << " ";
271  }
272  else{
273  if(output_opt[0].empty())
274  std::cout << x << " " << y << " " << dstnodata_opt[0] << endl;
275  else
276  outputStream << x << " " << y << " " << dstnodata_opt[0] << endl;
277  }
278  }
279  else{
280  switch(theResample){
281  case(BILINEAR):
282  lowerCol=readCol-0.5;
283  lowerCol=static_cast<int>(lowerCol);
284  upperCol=readCol+0.5;
285  upperCol=static_cast<int>(upperCol);
286  if(lowerCol<0)
287  lowerCol=0;
288  if(upperCol>=imgReader.nrOfCol())
289  upperCol=imgReader.nrOfCol()-1;
290  if(oformat_opt[0]=="matrix"){
291  if(output_opt[0].empty())
292  std::cout << (readCol-0.5-lowerCol)*readBuffer[upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[lowerCol-startCol] << " ";
293  else
294  outputStream << (readCol-0.5-lowerCol)*readBuffer[upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[lowerCol-startCol] << " ";
295  }
296  else if(!imgReader.isNoData(readBuffer[upperCol-startCol])&&!imgReader.isNoData(readBuffer[lowerCol-startCol])){
297  if(output_opt[0].empty())
298  std::cout << x << " " << y << " " << (readCol-0.5-lowerCol)*readBuffer[upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[lowerCol-startCol] << " " << endl;
299  else
300  outputStream << x << " " << y << " " << (readCol-0.5-lowerCol)*readBuffer[upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[lowerCol-startCol] << " " << endl;
301  }
302  break;
303  default:
304  readCol=static_cast<int>(readCol);
305  readCol-=startCol;//we only start reading from startCol
306  assert(readCol>=0);
307  if(readCol>=readBuffer.size())
308  std::cout << "Error: " << readCol << " >= " << readBuffer.size() << std::endl;
309  assert(readCol<readBuffer.size());
310  if(oformat_opt[0]=="matrix"){
311  if(output_opt[0].empty())
312  std::cout << readBuffer[readCol] << " ";
313  else
314  outputStream << readBuffer[readCol] << " ";
315  }
316  else if(!imgReader.isNoData(readBuffer[readCol])){
317  if(output_opt[0].empty())
318  std::cout << x << " " << y << " " << readBuffer[readCol] << std::endl;
319  else
320  outputStream << x << " " << y << " " << readBuffer[readCol] << std::endl;
321  }
322  break;
323  }
324  }
325  }
326  }
327  catch(string errorstring){
328  cout << errorstring << endl;
329  exit(1);
330  }
331  if(oformat_opt[0]=="matrix"){
332  if(output_opt[0].empty())
333  std::cout << std::endl;
334  else
335  outputStream << std::endl;
336  }
337  }
338  }
339  if(extent_opt[0]!=""){
340  extentReader.close();
341  }
342  imgReader.close();
343  if(!output_opt[0].empty())
344  outputStream.close();
345 }