pktools  2.6.3
Processing Kernel for geospatial data
pkcrop.cc
1 /**********************************************************************
2 pkcrop.cc: perform raster data operations on image such as crop, extract and stack bands
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 <assert.h>
21 #include <cstdlib>
22 #include <string>
23 #include <list>
24 #include <iostream>
25 #include <algorithm>
26 #include "imageclasses/ImgWriterGdal.h"
27 #include "imageclasses/ImgReaderGdal.h"
28 #include "imageclasses/ImgReaderOgr.h"
29 #include "base/Optionpk.h"
30 #include "algorithms/Egcs.h"
31 
32 /******************************************************************************/
94 using namespace std;
95 
96 int main(int argc, char *argv[])
97 {
98  Optionpk<string> input_opt("i", "input", "Input image file(s). If input contains multiple images, a multi-band output is created");
99  Optionpk<string> output_opt("o", "output", "Output image file");
100  Optionpk<string> projection_opt("a_srs", "a_srs", "Override the projection for the output file (leave blank to copy from input file, use epsg:3035 to use European projection and force to European grid");
101  //todo: support layer names
102  Optionpk<string> extent_opt("e", "extent", "get boundary from extent from polygons in vector file");
103  Optionpk<bool> cut_opt("cut", "crop_to_cutline", "Crop the extent of the target dataset to the extent of the cutline.",false);
104  Optionpk<string> mask_opt("m", "mask", "Use the first band of the specified file as a validity mask (0 is nodata).");
105  Optionpk<double> ulx_opt("ulx", "ulx", "Upper left x value bounding box", 0.0);
106  Optionpk<double> uly_opt("uly", "uly", "Upper left y value bounding box", 0.0);
107  Optionpk<double> lrx_opt("lrx", "lrx", "Lower right x value bounding box", 0.0);
108  Optionpk<double> lry_opt("lry", "lry", "Lower right y value bounding box", 0.0);
109  Optionpk<double> dx_opt("dx", "dx", "Output resolution in x (in meter) (empty: keep original resolution)");
110  Optionpk<double> dy_opt("dy", "dy", "Output resolution in y (in meter) (empty: keep original resolution)");
111  Optionpk<double> cx_opt("x", "x", "x-coordinate of image center to crop (in meter)");
112  Optionpk<double> cy_opt("y", "y", "y-coordinate of image center to crop (in meter)");
113  Optionpk<double> nx_opt("nx", "nx", "image size in x to crop (in meter)");
114  Optionpk<double> ny_opt("ny", "ny", "image size in y to crop (in meter)");
115  Optionpk<int> ns_opt("ns", "ns", "number of samples to crop (in pixels)");
116  Optionpk<int> nl_opt("nl", "nl", "number of lines to crop (in pixels)");
117  Optionpk<int> band_opt("b", "band", "band index to crop (leave empty to retain all bands)");
118  Optionpk<double> autoscale_opt("as", "autoscale", "scale output to min and max, e.g., --autoscale 0 --autoscale 255");
119  Optionpk<double> scale_opt("s", "scale", "output=scale*input+offset");
120  Optionpk<double> offset_opt("off", "offset", "output=scale*input+offset");
121  Optionpk<string> otype_opt("ot", "otype", "Data type for output image ({Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/CInt16/CInt32/CFloat32/CFloat64}). Empty string: inherit type from input image","");
122  Optionpk<string> oformat_opt("of", "oformat", "Output image format (see also gdal_translate). Empty string: inherit from input image");
123  Optionpk<string> option_opt("co", "co", "Creation option for output file. Multiple options can be specified.");
124  Optionpk<string> colorTable_opt("ct", "ct", "color table (file with 5 columns: id R G B ALFA (0: transparent, 255: solid)");
125  Optionpk<float> nodata_opt("nodata", "nodata", "Nodata value to put in image if out of bounds.");
126  Optionpk<string> resample_opt("r", "resampling-method", "Resampling method (near: nearest neighbor, bilinear: bi-linear interpolation).", "near");
127  Optionpk<string> description_opt("d", "description", "Set image description");
128  Optionpk<short> verbose_opt("v", "verbose", "verbose", 0,2);
129 
130  extent_opt.setHide(1);
131  cut_opt.setHide(1);
132  mask_opt.setHide(1);
133  option_opt.setHide(1);
134  cx_opt.setHide(1);
135  cy_opt.setHide(1);
136  nx_opt.setHide(1);
137  ny_opt.setHide(1);
138  ns_opt.setHide(1);
139  nl_opt.setHide(1);
140  scale_opt.setHide(1);
141  offset_opt.setHide(1);
142  nodata_opt.setHide(1);
143  description_opt.setHide(1);
144 
145  bool doProcess;//stop process when program was invoked with help option (-h --help)
146  try{
147  doProcess=input_opt.retrieveOption(argc,argv);
148  output_opt.retrieveOption(argc,argv);
149  projection_opt.retrieveOption(argc,argv);
150  ulx_opt.retrieveOption(argc,argv);
151  uly_opt.retrieveOption(argc,argv);
152  lrx_opt.retrieveOption(argc,argv);
153  lry_opt.retrieveOption(argc,argv);
154  band_opt.retrieveOption(argc,argv);
155  autoscale_opt.retrieveOption(argc,argv);
156  otype_opt.retrieveOption(argc,argv);
157  oformat_opt.retrieveOption(argc,argv);
158  colorTable_opt.retrieveOption(argc,argv);
159  dx_opt.retrieveOption(argc,argv);
160  dy_opt.retrieveOption(argc,argv);
161  resample_opt.retrieveOption(argc,argv);
162  extent_opt.retrieveOption(argc,argv);
163  cut_opt.retrieveOption(argc,argv);
164  mask_opt.retrieveOption(argc,argv);
165  option_opt.retrieveOption(argc,argv);
166  cx_opt.retrieveOption(argc,argv);
167  cy_opt.retrieveOption(argc,argv);
168  nx_opt.retrieveOption(argc,argv);
169  ny_opt.retrieveOption(argc,argv);
170  ns_opt.retrieveOption(argc,argv);
171  nl_opt.retrieveOption(argc,argv);
172  scale_opt.retrieveOption(argc,argv);
173  offset_opt.retrieveOption(argc,argv);
174  nodata_opt.retrieveOption(argc,argv);
175  description_opt.retrieveOption(argc,argv);
176  verbose_opt.retrieveOption(argc,argv);
177  }
178  catch(string predefinedString){
179  std::cout << predefinedString << std::endl;
180  exit(0);
181  }
182  if(verbose_opt[0])
183  cout << setprecision(12) << "--ulx=" << ulx_opt[0] << " --uly=" << uly_opt[0] << " --lrx=" << lrx_opt[0] << " --lry=" << lry_opt[0] << endl;
184 
185  if(!doProcess){
186  cout << endl;
187  cout << "Usage: pkcrop -i input -o output" << endl;
188  cout << endl;
189  std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
190  exit(0);//help was invoked, stop processing
191  }
192  if(input_opt.empty()){
193  std::cerr << "No input file provided (use option -i). Use --help for help information" << std::endl;
194  exit(0);
195  }
196  if(output_opt.empty()){
197  std::cerr << "No output file provided (use option -o). Use --help for help information" << std::endl;
198  exit(0);
199  }
200 
201  float nodataValue=nodata_opt.size()? nodata_opt[0] : 0;
202  RESAMPLE theResample;
203  if(resample_opt[0]=="near"){
204  theResample=NEAR;
205  if(verbose_opt[0])
206  cout << "resampling: nearest neighbor" << endl;
207  }
208  else if(resample_opt[0]=="bilinear"){
209  theResample=BILINEAR;
210  if(verbose_opt[0])
211  cout << "resampling: bilinear interpolation" << endl;
212  }
213  else{
214  std::cout << "Error: resampling method " << resample_opt[0] << " not supported" << std::endl;
215  exit(1);
216  }
217 
218  const char* pszMessage;
219  void* pProgressArg=NULL;
220  GDALProgressFunc pfnProgress=GDALTermProgress;
221  double progress=0;
222  pfnProgress(progress,pszMessage,pProgressArg);
223  ImgReaderGdal imgReader;
224  ImgWriterGdal imgWriter;
225  //open input images to extract number of bands and spatial resolution
226  int ncropband=0;//total number of bands to write
227  double dx=0;
228  double dy=0;
229  if(dx_opt.size())
230  dx=dx_opt[0];
231  if(dy_opt.size())
232  dy=dy_opt[0];
233 
234  bool isGeoRef=false;
235  string projectionString;
236  for(int iimg=0;iimg<input_opt.size();++iimg){
237  imgReader.open(input_opt[iimg]);
238  if(!isGeoRef)
239  isGeoRef=imgReader.isGeoRef();
240  if(imgReader.isGeoRef()&&projection_opt.empty())
241  projectionString=imgReader.getProjection();
242  if(dx_opt.empty()){
243  if(!iimg||imgReader.getDeltaX()<dx)
244  dx=imgReader.getDeltaX();
245  }
246  if(dy_opt.empty()){
247  if(!iimg||imgReader.getDeltaY()<dy)
248  dy=imgReader.getDeltaY();
249  }
250  if(band_opt.size())
251  ncropband+=band_opt.size();
252  else
253  ncropband+=imgReader.nrOfBand();
254  imgReader.close();
255  }
256 
257  GDALDataType theType=GDT_Unknown;
258  if(verbose_opt[0])
259  cout << "possible output data types: ";
260  for(int iType = 0; iType < GDT_TypeCount; ++iType){
261  if(verbose_opt[0])
262  cout << " " << GDALGetDataTypeName((GDALDataType)iType);
263  if( GDALGetDataTypeName((GDALDataType)iType) != NULL
264  && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
265  otype_opt[0].c_str()))
266  theType=(GDALDataType) iType;
267  }
268  if(verbose_opt[0]){
269  cout << endl;
270  if(theType==GDT_Unknown)
271  cout << "Unknown output pixel type: " << otype_opt[0] << endl;
272  else
273  cout << "Output pixel type: " << GDALGetDataTypeName(theType) << endl;
274  }
275  //bounding box of cropped image
276  double cropulx=ulx_opt[0];
277  double cropuly=uly_opt[0];
278  double croplrx=lrx_opt[0];
279  double croplry=lry_opt[0];
280  //get bounding box from extentReader if defined
281  ImgReaderOgr extentReader;
282 
283  if(extent_opt.size()){
284  double e_ulx;
285  double e_uly;
286  double e_lrx;
287  double e_lry;
288  for(int iextent=0;iextent<extent_opt.size();++iextent){
289  extentReader.open(extent_opt[iextent]);
290  if(!(extentReader.getExtent(e_ulx,e_uly,e_lrx,e_lry))){
291  cerr << "Error: could not get extent from " << extent_opt[0] << endl;
292  exit(1);
293  }
294  if(!iextent){
295  ulx_opt[0]=e_ulx;
296  uly_opt[0]=e_uly;
297  lrx_opt[0]=e_lrx;
298  lry_opt[0]=e_lry;
299  }
300  else{
301  if(e_ulx<ulx_opt[0])
302  ulx_opt[0]=e_ulx;
303  if(e_uly>uly_opt[0])
304  uly_opt[0]=e_uly;
305  if(e_lrx>lrx_opt[0])
306  lrx_opt[0]=e_lrx;
307  if(e_lry<lry_opt[0])
308  lry_opt[0]=e_lry;
309  }
310  extentReader.close();
311  }
312  if(cut_opt.size())
313  extentReader.open(extent_opt[0]);
314  }
315  else if(cx_opt.size()&&cy_opt.size()&&nx_opt.size()&&ny_opt.size()){
316  ulx_opt[0]=cx_opt[0]-nx_opt[0]/2.0;
317  uly_opt[0]=(isGeoRef) ? cy_opt[0]+ny_opt[0]/2.0 : cy_opt[0]-ny_opt[0]/2.0;
318  lrx_opt[0]=cx_opt[0]+nx_opt[0]/2.0;
319  lry_opt[0]=(isGeoRef) ? cy_opt[0]-ny_opt[0]/2.0 : cy_opt[0]+ny_opt[0]/2.0;
320  // if(cropulx<ulx_opt[0])
321  // cropulx=ulx_opt[0];
322  // if(cropuly>uly_opt[0])
323  // cropuly=uly_opt[0];
324  // if(croplrx>lrx_opt[0])
325  // croplrx=lrx_opt[0];
326  // if(croplry<lry_opt[0])
327  // croplry=lry_opt[0];
328  }
329  else if(cx_opt.size()&&cy_opt.size()&&ns_opt.size()&&nl_opt.size()){
330  ulx_opt[0]=cx_opt[0]-ns_opt[0]*dx/2.0;
331  uly_opt[0]=(isGeoRef) ? cy_opt[0]+nl_opt[0]*dy/2.0 : cy_opt[0]-nl_opt[0]*dy/2.0;
332  lrx_opt[0]=cx_opt[0]+ns_opt[0]*dx/2.0;
333  lry_opt[0]=(isGeoRef) ? cy_opt[0]-nl_opt[0]*dy/2.0 : cy_opt[0]+nl_opt[0]*dy/2.0;
334  // if(cropulx<ulx_opt[0])
335  // cropulx=ulx_opt[0];
336  // if(cropuly>uly_opt[0])
337  // cropuly=uly_opt[0];
338  // if(croplrx>lrx_opt[0])
339  // croplrx=lrx_opt[0];
340  // if(croplry<lry_opt[0])
341  // croplry=lry_opt[0];
342  }
343 
344  if(verbose_opt[0])
345  cout << "--ulx=" << ulx_opt[0] << " --uly=" << uly_opt[0] << " --lrx=" << lrx_opt[0] << " --lry=" << lry_opt[0] << endl;
346 
347  int ncropcol=0;
348  int ncroprow=0;
349 
350  ImgWriterGdal maskWriter;
351  if(extent_opt.size()&&cut_opt[0]){
352  try{
353  ncropcol=abs(static_cast<int>(ceil((lrx_opt[0]-ulx_opt[0])/dx)));
354  ncroprow=abs(static_cast<int>(ceil((uly_opt[0]-lry_opt[0])/dy)));
355  maskWriter.open("/vsimem/mask.tif",ncropcol,ncroprow,1,GDT_Float32,"GTiff",option_opt);
356  double gt[6];
357  gt[0]=ulx_opt[0];
358  gt[1]=dx;
359  gt[2]=0;
360  gt[3]=uly_opt[0];
361  gt[4]=0;
362  gt[5]=-dy;
363  maskWriter.setGeoTransform(gt);
364  if(projection_opt.size())
365  maskWriter.setProjectionProj4(projection_opt[0]);
366  else if(projectionString.size())
367  maskWriter.setProjection(projectionString);
368 
369  //todo: handle multiple extent options
370  vector<double> burnValues(1,1);//burn value is 1 (single band)
371  maskWriter.rasterizeOgr(extentReader,burnValues);
372  maskWriter.close();
373  }
374  catch(string error){
375  cerr << error << std::endl;
376  exit(2);
377  }
378  catch(...){
379  cerr << "error catched" << std::endl;
380  exit(1);
381  }
382  //todo: support multiple masks
383  mask_opt.clear();
384  mask_opt.push_back("/vsimem/mask.tif");
385  }
386  ImgReaderGdal maskReader;
387  if(mask_opt.size()){
388  try{
389  if(verbose_opt[0]>=1)
390  std::cout << "opening mask image file " << mask_opt[0] << std::endl;
391  maskReader.open(mask_opt[0]);
392  }
393  catch(string error){
394  cerr << error << std::endl;
395  exit(2);
396  }
397  catch(...){
398  cerr << "error catched" << std::endl;
399  exit(1);
400  }
401  }
402 
403  //determine number of output bands
404  int writeBand=0;//write band
405 
406  if(scale_opt.size()){
407  while(scale_opt.size()<band_opt.size())
408  scale_opt.push_back(scale_opt[0]);
409  }
410  if(offset_opt.size()){
411  while(offset_opt.size()<band_opt.size())
412  offset_opt.push_back(offset_opt[0]);
413  }
414  if(autoscale_opt.size()){
415  assert(autoscale_opt.size()%2==0);
416  // while(autoscale_opt.size()<band_opt.size()*2){
417  // autoscale_opt.push_back(autoscale_opt[0]);
418  // autoscale_opt.push_back(autoscale_opt[1]);
419  // }
420  }
421 
422  for(int iimg=0;iimg<input_opt.size();++iimg){
423  if(verbose_opt[0])
424  cout << "opening image " << input_opt[iimg] << endl;
425  imgReader.open(input_opt[iimg]);
426  //if output type not set, get type from input image
427  if(theType==GDT_Unknown){
428  theType=imgReader.getDataType();
429  if(verbose_opt[0])
430  cout << "Using data type from input image: " << GDALGetDataTypeName(theType) << endl;
431  }
432  if(option_opt.findSubstring("INTERLEAVE=")==option_opt.end()){
433  string theInterleave="INTERLEAVE=";
434  theInterleave+=imgReader.getInterleave();
435  option_opt.push_back(theInterleave);
436  }
437  int nrow=imgReader.nrOfRow();
438  int ncol=imgReader.nrOfCol();
439  // if(!dx||!dy){
440  // dx=imgReader.getDeltaX();
441  // dy=imgReader.getDeltaY();
442  // }
443  if(verbose_opt[0])
444  cout << "size of " << input_opt[iimg] << ": " << ncol << " cols, "<< nrow << " rows" << endl;
445  double uli,ulj,lri,lrj;//image coordinates
446  bool forceEUgrid=false;
447  if(projection_opt.size())
448  forceEUgrid=(!(projection_opt[0].compare("EPSG:3035"))||!(projection_opt[0].compare("EPSG:3035"))||projection_opt[0].find("ETRS-LAEA")!=string::npos);
449  if(ulx_opt[0]>=lrx_opt[0]){//default bounding box: no cropping
450  uli=0;
451  lri=imgReader.nrOfCol()-1;
452  ulj=0;
453  lrj=imgReader.nrOfRow()-1;
454  ncropcol=imgReader.nrOfCol();
455  ncroprow=imgReader.nrOfRow();
456  imgReader.getBoundingBox(cropulx,cropuly,croplrx,croplry);
457  double magicX=1,magicY=1;
458  // imgReader.getMagicPixel(magicX,magicY);
459  if(forceEUgrid){
460  //force to LAEA grid
461  Egcs egcs;
462  egcs.setLevel(egcs.res2level(dx));
463  egcs.force2grid(cropulx,cropuly,croplrx,croplry);
464  imgReader.geo2image(cropulx+(magicX-1.0)*imgReader.getDeltaX(),cropuly-(magicY-1.0)*imgReader.getDeltaY(),uli,ulj);
465  imgReader.geo2image(croplrx+(magicX-2.0)*imgReader.getDeltaX(),croplry-(magicY-2.0)*imgReader.getDeltaY(),lri,lrj);
466  }
467  imgReader.geo2image(cropulx+(magicX-1.0)*imgReader.getDeltaX(),cropuly-(magicY-1.0)*imgReader.getDeltaY(),uli,ulj);
468  imgReader.geo2image(croplrx+(magicX-2.0)*imgReader.getDeltaX(),croplry-(magicY-2.0)*imgReader.getDeltaY(),lri,lrj);
469  //test
470  ncropcol=abs(static_cast<int>(ceil((croplrx-cropulx)/dx)));
471  ncroprow=abs(static_cast<int>(ceil((cropuly-croplry)/dy)));
472  }
473  else{
474  double magicX=1,magicY=1;
475  // imgReader.getMagicPixel(magicX,magicY);
476  cropulx=ulx_opt[0];
477  cropuly=uly_opt[0];
478  croplrx=lrx_opt[0];
479  croplry=lry_opt[0];
480  if(forceEUgrid){
481  //force to LAEA grid
482  Egcs egcs;
483  egcs.setLevel(egcs.res2level(dx));
484  egcs.force2grid(cropulx,cropuly,croplrx,croplry);
485  imgReader.geo2image(cropulx+(magicX-1.0)*imgReader.getDeltaX(),cropuly-(magicY-1.0)*imgReader.getDeltaY(),uli,ulj);
486  imgReader.geo2image(croplrx+(magicX-2.0)*imgReader.getDeltaX(),croplry-(magicY-2.0)*imgReader.getDeltaY(),lri,lrj);
487  }
488  imgReader.geo2image(cropulx+(magicX-1.0)*imgReader.getDeltaX(),cropuly-(magicY-1.0)*imgReader.getDeltaY(),uli,ulj);
489  imgReader.geo2image(croplrx+(magicX-2.0)*imgReader.getDeltaX(),croplry-(magicY-2.0)*imgReader.getDeltaY(),lri,lrj);
490 
491  ncropcol=abs(static_cast<int>(ceil((croplrx-cropulx)/dx)));
492  ncroprow=abs(static_cast<int>(ceil((cropuly-croplry)/dy)));
493  uli=floor(uli);
494  ulj=floor(ulj);
495  lri=floor(lri);
496  lrj=floor(lrj);
497  }
498 
499  double dcropcol=0;
500  double dcroprow=0;
501  double deltaX=imgReader.getDeltaX();
502  double deltaY=imgReader.getDeltaY();
503  dcropcol=(lri-uli+1)/(dx/deltaX);
504  dcroprow=(lrj-ulj+1)/(dy/deltaY);
505  if(!imgWriter.nrOfBand()){//not opened yet
506  if(verbose_opt[0]){
507  cout << "cropulx: " << cropulx << endl;
508  cout << "cropuly: " << cropuly << endl;
509  cout << "croplrx: " << croplrx << endl;
510  cout << "croplry: " << croplry << endl;
511  cout << "ncropcol: " << ncropcol << endl;
512  cout << "ncroprow: " << ncroprow << endl;
513  cout << "cropulx+ncropcol*dx: " << cropulx+ncropcol*dx << endl;
514  cout << "cropuly-ncroprow*dy: " << cropuly-ncroprow*dy << endl;
515  cout << "upper left column of input image: " << uli << endl;
516  cout << "upper left row of input image: " << ulj << endl;
517  cout << "lower right column of input image: " << lri << endl;
518  cout << "lower right row of input image: " << lrj << endl;
519  cout << "new number of cols: " << ncropcol << endl;
520  cout << "new number of rows: " << ncroprow << endl;
521  cout << "new number of bands: " << ncropband << endl;
522  }
523  // string theCompression;
524  // if(compress_opt[0]!="")//default
525  // theCompression=compress_opt[0];
526  // else
527  // theCompression=imgReader.getCompression();
528  // string theInterleave;
529  // if(interleave_opt[0]!="")//default
530  // theInterleave=interleave_opt[0];
531  // else
532  // theInterleave=imgReader.getInterleave();
533  string imageType=imgReader.getImageType();
534  if(oformat_opt.size())//default
535  imageType=oformat_opt[0];
536  try{
537  imgWriter.open(output_opt[0],ncropcol,ncroprow,ncropband,theType,imageType,option_opt);
538  if(nodata_opt.size()){
539  for(int iband=0;iband<ncropband;++iband)
540  imgWriter.GDALSetNoDataValue(nodata_opt[0],iband);
541  }
542  }
543  catch(string errorstring){
544  cout << errorstring << endl;
545  exit(4);
546  }
547  if(description_opt.size())
548  imgWriter.setImageDescription(description_opt[0]);
549  double gt[6];
550  gt[0]=cropulx;
551  gt[1]=dx;
552  gt[2]=0;
553  gt[3]=cropuly;
554  gt[4]=0;
555  gt[5]=(imgReader.isGeoRef())? -dy : dy;
556  imgWriter.setGeoTransform(gt);
557  if(projection_opt.size()){
558  if(verbose_opt[0])
559  cout << "projection: " << projection_opt[0] << endl;
560  imgWriter.setProjectionProj4(projection_opt[0]);
561  }
562  else
563  imgWriter.setProjection(imgReader.getProjection());
564  if(imgWriter.getDataType()==GDT_Byte){
565  if(colorTable_opt.size()){
566  if(colorTable_opt[0]!="none")
567  imgWriter.setColorTable(colorTable_opt[0]);
568  }
569  else if (imgReader.getColorTable()!=NULL)//copy colorTable from input image
570  imgWriter.setColorTable(imgReader.getColorTable());
571  }
572  }
573 
574  double startCol=uli;
575  double endCol=lri;
576  if(uli<0)
577  startCol=0;
578  else if(uli>=imgReader.nrOfCol())
579  startCol=imgReader.nrOfCol()-1;
580  if(lri<0)
581  endCol=0;
582  else if(lri>=imgReader.nrOfCol())
583  endCol=imgReader.nrOfCol()-1;
584  double startRow=ulj;
585  double endRow=lrj;
586  if(ulj<0)
587  startRow=0;
588  else if(ulj>=imgReader.nrOfRow())
589  startRow=imgReader.nrOfRow()-1;
590  if(lrj<0)
591  endRow=0;
592  else if(lrj>=imgReader.nrOfRow())
593  endRow=imgReader.nrOfRow()-1;
594 
595 
596 
597  int readncol=endCol-startCol+1;
598  vector<double> readBuffer(readncol+1);
599  int nband=(band_opt.size())?band_opt.size() : imgReader.nrOfBand();
600  for(int iband=0;iband<nband;++iband){
601  int readBand=(band_opt.size()>iband)?band_opt[iband]:iband;
602  if(verbose_opt[0]){
603  cout << "extracting band " << readBand << endl;
604  pfnProgress(progress,pszMessage,pProgressArg);
605  }
606  double theMin=0;
607  double theMax=0;
608  if(autoscale_opt.size()){
609  try{
610  imgReader.getMinMax(static_cast<int>(startCol),static_cast<int>(endCol),static_cast<int>(startRow),static_cast<int>(endRow),readBand,theMin,theMax);
611  }
612  catch(string errorString){
613  cout << errorString << endl;
614  }
615  if(verbose_opt[0])
616  cout << "minmax: " << theMin << ", " << theMax << endl;
617  double theScale=(autoscale_opt[1]-autoscale_opt[0])/(theMax-theMin);
618  double theOffset=autoscale_opt[0]-theScale*theMin;
619  imgReader.setScale(theScale,readBand);
620  imgReader.setOffset(theOffset,readBand);
621  }
622  else{
623  if(scale_opt.size()){
624  if(scale_opt.size()>iband)
625  imgReader.setScale(scale_opt[iband],readBand);
626  else
627  imgReader.setScale(scale_opt[0],readBand);
628  }
629  if(offset_opt.size()){
630  if(offset_opt.size()>iband)
631  imgReader.setOffset(offset_opt[iband],readBand);
632  else
633  imgReader.setOffset(offset_opt[0],readBand);
634  }
635  }
636 
637  double readRow=0;
638  double readCol=0;
639  double lowerCol=0;
640  double upperCol=0;
641  for(int irow=0;irow<imgWriter.nrOfRow();++irow){
642  vector<float> lineMask;
643  double x=0;
644  double y=0;
645  //convert irow to geo
646  imgWriter.image2geo(0,irow,x,y);
647  //lookup corresponding row for irow in this file
648  imgReader.geo2image(x,y,readCol,readRow);
649  vector<double> writeBuffer;
650  if(readRow<0||readRow>=imgReader.nrOfRow()){
651  //if(readRow<0)
652  //readRow=0;
653  //else if(readRow>=imgReader.nrOfRow())
654  //readRow=imgReader.nrOfRow()-1;
655  for(int ib=0;ib<imgWriter.nrOfCol();++ib)
656  writeBuffer.push_back(nodataValue);
657  }
658  else{
659  if(verbose_opt[0]>1)
660  cout << "reading row: " << readRow << endl;
661  try{
662  if(endCol<imgReader.nrOfCol()-1)
663  imgReader.readData(readBuffer,GDT_Float64,startCol,endCol+1,readRow,readBand,theResample);
664  else
665  imgReader.readData(readBuffer,GDT_Float64,startCol,endCol,readRow,readBand,theResample);
666  // for(int ib=0;ib<ncropcol;++ib){
667  double oldRowMask=-1;//keep track of row mask to optimize number of line readings
668  for(int ib=0;ib<imgWriter.nrOfCol();++ib){
669  imgWriter.image2geo(ib,irow,x,y);
670  //lookup corresponding row for irow in this file
671  imgReader.geo2image(x,y,readCol,readRow);
672  if(readCol<0||readCol>=imgReader.nrOfCol()){
673  // if(readCol<0||readCol>=imgReader.nrOfCol()){
674  // if(readCol<0)
675  // readCol=0;
676  // else if(readCol>=imgReader.nrOfCol())
677  // readCol=imgReader.nrOfCol()-1;
678  writeBuffer.push_back(nodataValue);
679  }
680  else{
681  bool valid=true;
682  double geox=0;
683  double geoy=0;
684  if(mask_opt.size()){
685  //read mask
686  double colMask=0;
687  double rowMask=0;
688 
689  imgWriter.image2geo(ib,irow,geox,geoy);
690  maskReader.geo2image(geox,geoy,colMask,rowMask);
691  colMask=static_cast<int>(colMask);
692  rowMask=static_cast<int>(rowMask);
693  if(rowMask>=0&&rowMask<maskReader.nrOfRow()&&colMask>=0&&colMask<maskReader.nrOfCol()){
694  if(static_cast<int>(rowMask)!=static_cast<int>(oldRowMask)){
695 
696  assert(rowMask>=0&&rowMask<maskReader.nrOfRow());
697  try{
698  maskReader.readData(lineMask,GDT_Float32,static_cast<int>(rowMask));
699  }
700  catch(string errorstring){
701  cerr << errorstring << endl;
702  exit(1);
703  }
704  catch(...){
705  cerr << "error catched" << std::endl;
706  exit(3);
707  }
708  oldRowMask=rowMask;
709  }
710  if(lineMask[colMask]==0)
711  valid=false;
712  }
713  }
714 
715  if(!valid)
716  writeBuffer.push_back(nodataValue);
717  else{
718  switch(theResample){
719  case(BILINEAR):
720  lowerCol=readCol-0.5;
721  lowerCol=static_cast<int>(lowerCol);
722  upperCol=readCol+0.5;
723  upperCol=static_cast<int>(upperCol);
724  if(lowerCol<0)
725  lowerCol=0;
726  if(upperCol>=imgReader.nrOfCol())
727  upperCol=imgReader.nrOfCol()-1;
728  // writeBuffer.push_back((readCol-0.5-lowerCol)*(readBuffer[upperCol-startCol]*theScale+theOffset)+(1-readCol+0.5+lowerCol)*(readBuffer[lowerCol-startCol]*theScale+theOffset));
729  writeBuffer.push_back((readCol-0.5-lowerCol)*readBuffer[upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[lowerCol-startCol]);
730  break;
731  default:
732  readCol=static_cast<int>(readCol);
733  readCol-=startCol;//we only start reading from startCol
734  // writeBuffer.push_back(readBuffer[readCol]*theScale+theOffset);
735  writeBuffer.push_back(readBuffer[readCol]);
736  break;
737  }
738  }
739  }
740  }
741  }
742  catch(string errorstring){
743  cout << errorstring << endl;
744  exit(2);
745  }
746  }
747  if(writeBuffer.size()!=imgWriter.nrOfCol())
748  cout << "writeBuffer.size()=" << writeBuffer.size() << ", imgWriter.nrOfCol()=" << imgWriter.nrOfCol() << endl;
749  assert(writeBuffer.size()==imgWriter.nrOfCol());
750  try{
751  imgWriter.writeData(writeBuffer,GDT_Float64,irow,writeBand);
752  }
753  catch(string errorstring){
754  cout << errorstring << endl;
755  exit(3);
756  }
757  if(verbose_opt[0]){
758  progress=(1.0+irow);
759  progress/=imgWriter.nrOfRow();
760  pfnProgress(progress,pszMessage,pProgressArg);
761  }
762  else{
763  progress=(1.0+irow);
764  progress+=(imgWriter.nrOfRow()*writeBand);
765  progress/=imgWriter.nrOfBand()*imgWriter.nrOfRow();
766  assert(progress>=0);
767  assert(progress<=1);
768  pfnProgress(progress,pszMessage,pProgressArg);
769  }
770  }
771  ++writeBand;
772  }
773  imgReader.close();
774  }
775  if(extent_opt.size()&&cut_opt.size()){
776  extentReader.close();
777  }
778  imgWriter.close();
779 }
Definition: Egcs.h:26