pktools 2.6.7
Processing Kernel for geospatial data
pkcomposite.cc
1/**********************************************************************
2pkcomposite.cc: program to mosaic and composite geo-referenced images
3Copyright (C) 2008-2014 Pieter Kempeneers
4
5This file is part of pktools
6
7pktools is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
11
12pktools is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with pktools. If not, see <http://www.gnu.org/licenses/>.
19***********************************************************************/
20#include <algorithm>
21#include <vector>
22#include <iostream>
23#include <string>
24#include <math.h>
25#include "imageclasses/ImgReaderGdal.h"
26#include "imageclasses/ImgWriterGdal.h"
27#include "imageclasses/ImgReaderOgr.h"
28#include "base/Vector2d.h"
29#include "base/Optionpk.h"
30#include "algorithms/StatFactory.h"
31
32/******************************************************************************/
139namespace crule{
140 enum CRULE_TYPE {overwrite=0, maxndvi=1, maxband=2, minband=3, validband=4, mean=5, mode=6, median=7,sum=8,minallbands=9,maxallbands=10,stdev=11};
141}
142
143using namespace std;
144
145int main(int argc, char *argv[])
146{
147 Optionpk<string> input_opt("i", "input", "Input image file(s). If input contains multiple images, a multi-band output is created");
148 Optionpk<string> output_opt("o", "output", "Output image file");
149 Optionpk<int> band_opt("b", "band", "band index(es) to crop (leave empty if all bands must be retained)");
150 Optionpk<double> dx_opt("dx", "dx", "Output resolution in x (in meter) (empty: keep original resolution)");
151 Optionpk<double> dy_opt("dy", "dy", "Output resolution in y (in meter) (empty: keep original resolution)");
152 Optionpk<string> extent_opt("e", "extent", "get boundary from extent from polygons in vector file");
153 Optionpk<bool> cut_opt("cut", "crop_to_cutline", "Crop the extent of the target dataset to the extent of the cutline.",false);
154 Optionpk<string> eoption_opt("eo","eo", "special extent options controlling rasterization: ATTRIBUTE|CHUNKYSIZE|ALL_TOUCHED|BURN_VALUE_FROM|MERGE_ALG, e.g., -eo ATTRIBUTE=fieldname");
155 Optionpk<string> mask_opt("m", "mask", "Use the first band of the specified file as a validity mask (0 is nodata).");
156 Optionpk<float> msknodata_opt("msknodata", "msknodata", "Mask value not to consider for composite.", 0);
157 Optionpk<short> mskband_opt("mskband", "mskband", "Mask band to read (0 indexed)", 0);
158 Optionpk<double> ulx_opt("ulx", "ulx", "Upper left x value bounding box", 0.0);
159 Optionpk<double> uly_opt("uly", "uly", "Upper left y value bounding box", 0.0);
160 Optionpk<double> lrx_opt("lrx", "lrx", "Lower right x value bounding box", 0.0);
161 Optionpk<double> lry_opt("lry", "lry", "Lower right y value bounding box", 0.0);
162 Optionpk<string> crule_opt("cr", "crule", "Composite rule (overwrite, maxndvi, maxband, minband, mean, mode (only for byte images), median, sum, maxallbands, minallbands, stdev", "overwrite");
163 Optionpk<int> ruleBand_opt("cb", "cband", "band index used for the composite rule (e.g., for ndvi, use --cband=0 --cband=1 with 0 and 1 indices for red and nir band respectively", 0);
164 Optionpk<double> srcnodata_opt("srcnodata", "srcnodata", "invalid value(s) for input raster dataset");
165 Optionpk<int> bndnodata_opt("bndnodata", "bndnodata", "Band(s) in input image to check if pixel is valid (used for srcnodata, min and max options)", 0);
166 Optionpk<double> minValue_opt("min", "min", "flag values smaller or equal to this value as invalid.");
167 Optionpk<double> maxValue_opt("max", "max", "flag values larger or equal to this value as invalid.");
168 Optionpk<double> dstnodata_opt("dstnodata", "dstnodata", "nodata value to put in output raster dataset if not valid or out of bounds.", 0);
169 Optionpk<string> resample_opt("r", "resampling-method", "Resampling method (near: nearest neighbor, bilinear: bi-linear interpolation).", "near");
170 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", "");
171 Optionpk<string> oformat_opt("of", "oformat", "Output image format (see also gdal_translate).","GTiff");
172 Optionpk<string> option_opt("co", "co", "Creation option for output file. Multiple options can be specified.");
173 Optionpk<string> projection_opt("a_srs", "a_srs", "Override the spatial reference for the output file (leave blank to copy from input file, use epsg:3035 to use European projection and force to European grid");
174 Optionpk<short> file_opt("file", "file", "write number of observations (1) or sequence nr of selected file (2) for each pixels as additional layer in composite", 0);
175 Optionpk<short> weight_opt("w", "weight", "Weights (type: short) for the composite, use one weight for each input file in same order as input files are provided). Use value 1 for equal weights.", 1);
176 Optionpk<short> class_opt("c", "class", "classes for multi-band output image: each band represents the number of observations for one specific class. Use value 0 for no multi-band output image.", 0);
177 Optionpk<string> colorTable_opt("ct", "ct", "color table file with 5 columns: id R G B ALFA (0: transparent, 255: solid)");
178 Optionpk<string> description_opt("d", "description", "Set image description");
179 Optionpk<bool> align_opt("align", "align", "Align output bounding box to input image",false);
180 Optionpk<double> scale_opt("scale", "scale", "output=scale*input+offset");
181 Optionpk<double> offset_opt("offset", "offset", "output=scale*input+offset");
182 Optionpk<short> verbose_opt("v", "verbose", "verbose", 0,2);
183
184 extent_opt.setHide(1);
185 cut_opt.setHide(1);
186 eoption_opt.setHide(1);
187 mask_opt.setHide(1);
188 msknodata_opt.setHide(1);
189 mskband_opt.setHide(1);
190 option_opt.setHide(1);
191 file_opt.setHide(1);
192 weight_opt.setHide(1);
193 class_opt.setHide(1);
194 colorTable_opt.setHide(1);
195 description_opt.setHide(1);
196 scale_opt.setHide(1);
197 offset_opt.setHide(1);
198
199 bool doProcess;//stop process when program was invoked with help option (-h --help)
200 try{
201 doProcess=input_opt.retrieveOption(argc,argv);
202 output_opt.retrieveOption(argc,argv);
203 band_opt.retrieveOption(argc,argv);
204 dx_opt.retrieveOption(argc,argv);
205 dy_opt.retrieveOption(argc,argv);
206 extent_opt.retrieveOption(argc,argv);
207 cut_opt.retrieveOption(argc,argv);
208 eoption_opt.retrieveOption(argc,argv);
209 mask_opt.retrieveOption(argc,argv);
210 msknodata_opt.retrieveOption(argc,argv);
211 mskband_opt.retrieveOption(argc,argv);
212 ulx_opt.retrieveOption(argc,argv);
213 uly_opt.retrieveOption(argc,argv);
214 lrx_opt.retrieveOption(argc,argv);
215 lry_opt.retrieveOption(argc,argv);
216 crule_opt.retrieveOption(argc,argv);
217 ruleBand_opt.retrieveOption(argc,argv);
218 srcnodata_opt.retrieveOption(argc,argv);
219 bndnodata_opt.retrieveOption(argc,argv);
220 minValue_opt.retrieveOption(argc,argv);
221 maxValue_opt.retrieveOption(argc,argv);
222 dstnodata_opt.retrieveOption(argc,argv);
223 resample_opt.retrieveOption(argc,argv);
224 otype_opt.retrieveOption(argc,argv);
225 oformat_opt.retrieveOption(argc,argv);
226 option_opt.retrieveOption(argc,argv);
227 projection_opt.retrieveOption(argc,argv);
228 file_opt.retrieveOption(argc,argv);
229 weight_opt.retrieveOption(argc,argv);
230 class_opt.retrieveOption(argc,argv);
231 colorTable_opt.retrieveOption(argc,argv);
232 description_opt.retrieveOption(argc,argv);
233 align_opt.retrieveOption(argc,argv);
234 scale_opt.retrieveOption(argc,argv);
235 offset_opt.retrieveOption(argc,argv);
236 verbose_opt.retrieveOption(argc,argv);
237 }
238 catch(string predefinedString){
239 std::cout << predefinedString << std::endl;
240 exit(0);
241 }
242 if(!doProcess){
243 cout << endl;
244 cout << "Usage: pkcomposite -i input [-i input]* -o output" << endl;
245 cout << endl;
246 std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
247 exit(0);//help was invoked, stop processing
248 }
249
250 std::map<std::string, crule::CRULE_TYPE> cruleMap;
251 // //initialize cruleMap
252 // enum CRULE_TYPE {overwrite=0, maxndvi=1, maxband=2, minband=3, validband=4, mean=5, mode=6, median=7,sum=8};
253
254 cruleMap["overwrite"]=crule::overwrite;
255 cruleMap["maxndvi"]=crule::maxndvi;
256 cruleMap["maxband"]=crule::maxband;
257 cruleMap["minband"]=crule::minband;
258 cruleMap["validband"]=crule::validband;
259 cruleMap["mean"]=crule::mean;
260 cruleMap["mode"]=crule::mode;
261 cruleMap["median"]=crule::median;
262 cruleMap["sum"]=crule::sum;
263 cruleMap["maxallbands"]=crule::maxallbands;
264 cruleMap["minallbands"]=crule::minallbands;
265 cruleMap["stdev"]=crule::stdev;
266
267 if(srcnodata_opt.size()){
268 while(srcnodata_opt.size()<bndnodata_opt.size())
269 srcnodata_opt.push_back(srcnodata_opt[0]);
270 }
271 while(bndnodata_opt.size()<srcnodata_opt.size())
272 bndnodata_opt.push_back(bndnodata_opt[0]);
273 if(minValue_opt.size()){
274 while(minValue_opt.size()<bndnodata_opt.size())
275 minValue_opt.push_back(minValue_opt[0]);
276 while(bndnodata_opt.size()<minValue_opt.size())
277 bndnodata_opt.push_back(bndnodata_opt[0]);
278 }
279 if(maxValue_opt.size()){
280 while(maxValue_opt.size()<bndnodata_opt.size())
281 maxValue_opt.push_back(maxValue_opt[0]);
282 while(bndnodata_opt.size()<maxValue_opt.size())
283 bndnodata_opt.push_back(bndnodata_opt[0]);
284 }
285
286 RESAMPLE theResample;
287 if(resample_opt[0]=="near"){
288 theResample=NEAR;
289 if(verbose_opt[0])
290 cout << "resampling: nearest neighbor" << endl;
291 }
292 else if(resample_opt[0]=="bilinear"){
293 theResample=BILINEAR;
294 if(verbose_opt[0])
295 cout << "resampling: bilinear interpolation" << endl;
296 }
297 else{
298 std::cout << "Error: resampling method " << resample_opt[0] << " not supported" << std::endl;
299 exit(1);
300 }
301
302 if(input_opt.empty()){
303 std::cerr << "No input file provided (use option -i). Use --help for help information" << std::endl;
304 exit(0);
305 }
306 int nband=0;
307 int nwriteBand=0;
308 int writeBand=0;
309 vector<short> bands;
310
311 //get bounding box
312 double maxLRX=lrx_opt[0];
313 double maxULY=uly_opt[0];
314 double minULX=ulx_opt[0];
315 double minLRY=lry_opt[0];
316 double magic_x=1,magic_y=1;//magic pixel for GDAL map info
317
318 GDALDataType theType=GDT_Unknown;
319 if(verbose_opt[0])
320 cout << "possible output data types: ";
321 for(int iType = 0; iType < GDT_TypeCount; ++iType){
322 if(verbose_opt[0])
323 cout << " " << GDALGetDataTypeName((GDALDataType)iType);
324 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
325 && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
326 otype_opt[0].c_str()))
327 theType=(GDALDataType) iType;
328 }
329 if(verbose_opt[0]){
330 cout << endl;
331 if(theType==GDT_Unknown)
332 cout << "Unknown output pixel type: " << otype_opt[0] << endl;
333 else
334 cout << "Output pixel type: " << GDALGetDataTypeName(theType) << endl;
335 }
336
337 double dx=0;
338 double dy=0;
339 //get bounding box from extentReader if defined
340 ImgReaderOgr extentReader;
341 if(extent_opt.size()){
342 double e_ulx;
343 double e_uly;
344 double e_lrx;
345 double e_lry;
346 for(int iextent=0;iextent<extent_opt.size();++iextent){
347 extentReader.open(extent_opt[iextent]);
348 if(!(extentReader.getExtent(e_ulx,e_uly,e_lrx,e_lry))){
349 cerr << "Error: could not get extent from " << extent_opt[0] << endl;
350 exit(1);
351 }
352 if(!iextent){
353 ulx_opt[0]=e_ulx;
354 uly_opt[0]=e_uly;
355 lrx_opt[0]=e_lrx;
356 lry_opt[0]=e_lry;
357 }
358 else{
359 if(e_ulx<ulx_opt[0])
360 ulx_opt[0]=e_ulx;
361 if(e_uly>uly_opt[0])
362 uly_opt[0]=e_uly;
363 if(e_lrx>lrx_opt[0])
364 lrx_opt[0]=e_lrx;
365 if(e_lry<lry_opt[0])
366 lry_opt[0]=e_lry;
367 }
368 extentReader.close();
369 }
370 if(maxLRX>minULX&&minULX>ulx_opt[0])
371 ulx_opt[0]=minULX;
372 if(maxLRX>minULX&&maxLRX<lrx_opt[0])
373 lrx_opt[0]=maxLRX;
374 if(maxULY>minLRY&&maxULY<uly_opt[0])
375 uly_opt[0]=maxULY;
376 if(minLRY<maxULY&&minLRY>lry_opt[0])
377 lry_opt[0]=minLRY;
378 if(cut_opt.size()||eoption_opt.size())
379 extentReader.open(extent_opt[0]);
380 }
381
382 if(verbose_opt[0])
383 cout << "--ulx=" << ulx_opt[0] << " --uly=" << uly_opt[0] << " --lrx=" << lrx_opt[0] << " --lry=" << lry_opt[0] << endl;
384
385 vector<ImgReaderGdal> imgReader(input_opt.size());
386 // vector<ImgReaderGdal> imgReader(input_opt.size());
387 string theProjection="";
388 GDALColorTable* theColorTable=NULL;
389 string imageType;
390 bool init=false;
391 for(int ifile=0;ifile<input_opt.size();++ifile){
392 try{
393 imgReader[ifile].open(input_opt[ifile],GA_ReadOnly);
394 // imgReader[ifile].open(input_opt[ifile],GA_ReadOnly);
395 for(int iband=0;iband<scale_opt.size();++iband)
396 imgReader[ifile].setScale(scale_opt[iband],iband);
397 for(int iband=0;iband<offset_opt.size();++iband)
398 imgReader[ifile].setOffset(offset_opt[iband],iband);
399 }
400 catch(string errorstring){
401 cerr << errorstring << " " << input_opt[ifile] << endl;
402 }
403 //todo: must be in init part only?
404 if(colorTable_opt.empty())
405 if(imgReader[ifile].getColorTable())
406 theColorTable=(imgReader[ifile].getColorTable()->Clone());
407 if(projection_opt.empty())
408 theProjection=imgReader[ifile].getProjection();
409 if(option_opt.findSubstring("INTERLEAVE=")==option_opt.end()){
410 string theInterleave="INTERLEAVE=";
411 theInterleave+=imgReader[ifile].getInterleave();
412 option_opt.push_back(theInterleave);
413 }
414
415 if((ulx_opt[0]||uly_opt[0]||lrx_opt[0]||lry_opt[0])&&(!imgReader[ifile].covers(ulx_opt[0],uly_opt[0],lrx_opt[0],lry_opt[0]))){
416 if(verbose_opt[0])
417 cout << input_opt[ifile] << " not within bounding box, skipping..." << endl;
418 continue;
419 }
420 double theULX, theULY, theLRX, theLRY;
421 imgReader[ifile].getBoundingBox(theULX,theULY,theLRX,theLRY);
422 if(theLRY>theULY){
423 cerr << "Error: " << input_opt[ifile] << " is not georeferenced, only referenced images are supported for pkcomposite " << endl;
424 exit(1);
425 }
426 if(verbose_opt[0])
427 cout << "Bounding Box (ULX ULY LRX LRY): " << fixed << setprecision(6) << theULX << " " << theULY << " " << theLRX << " " << theLRY << endl;
428 if(!init){
429 if(verbose_opt[0]){
430 switch(cruleMap[crule_opt[0]]){
431 default:
432 case(crule::overwrite):
433 cout << "Composite rule: overwrite" << endl;
434 break;
435 case(crule::maxndvi):
436 cout << "Composite rule: max ndvi" << endl;
437 break;
438 case(crule::maxband):
439 cout << "Composite rule: max band" << endl;
440 break;
441 case(crule::minband):
442 cout << "Composite rule: min band" << endl;
443 break;
444 case(crule::validband):
445 cout << "Composite rule: valid band" << endl;
446 break;
447 case(crule::mean):
448 cout << "Composite rule: mean value" << endl;
449 break;
450 case(crule::mode):
451 cout << "Composite rule: max voting (only for byte images)" << endl;
452 break;
453 case(crule::median):
454 cout << "Composite rule: median" << endl;
455 break;
456 case(crule::stdev):
457 cout << "Composite rule: stdev" << endl;
458 break;
459 case(crule::sum):
460 cout << "Composite rule: sum" << endl;
461 break;
462 case(crule::minallbands):
463 cout << "Composite rule: minallbands" << endl;
464 break;
465 case(crule::maxallbands):
466 cout << "Composite rule: maxallbands" << endl;
467 break;
468 }
469 }
470 if(band_opt.size()){
471 nband=band_opt.size();
472 bands.resize(band_opt.size());
473 for(int iband=0;iband<band_opt.size();++iband){
474 bands[iband]=band_opt[iband];
475 assert(bands[iband]<imgReader[ifile].nrOfBand());
476 }
477 }
478 else{
479 nband=imgReader[ifile].nrOfBand();
480 bands.resize(nband);
481 for(int iband=0;iband<nband;++iband)
482 bands[iband]=iband;
483 }
484 for(int iband=0;iband<bndnodata_opt.size();++iband){
485 assert(bndnodata_opt[iband]>=0&&bndnodata_opt[iband]<nband);
486 }
487 //if output type not set, get type from input image
488 if(theType==GDT_Unknown){
489 theType=imgReader[ifile].getDataType();
490 if(verbose_opt[0])
491 cout << "Using data type from input image: " << GDALGetDataTypeName(theType) << endl;
492 }
493
494 if(oformat_opt.size())//default
495 imageType=oformat_opt[0];
496 else
497 imageType=imgReader[ifile].getImageType();
498
499 if(verbose_opt[0]){
500 cout << "type of data for " << input_opt[ifile] << ": " << theType << endl;
501 cout << "nband: " << nband << endl;
502 }
503
504 maxLRX=theLRX;
505 maxULY=theULY;
506 minULX=theULX;
507 minLRY=theLRY;
508 if(dx_opt.size())
509 dx=dx_opt[0];
510 else
511 dx=imgReader[ifile].getDeltaX();
512 if(dy_opt.size())
513 dy=dy_opt[0];
514 else
515 dy=imgReader[ifile].getDeltaY();
516 init=true;
517 }
518 else{
519 maxLRX=(theLRX>maxLRX)?theLRX:maxLRX;
520 maxULY=(theULY>maxULY)?theULY:maxULY;
521 minULX=(theULX<minULX)?theULX:minULX;
522 minLRY=(theLRY<minLRY)?theLRY:minLRY;
523 }
524 // imgReader.close();
525 }
526 if(verbose_opt[0])
527 cout << "bounding box input images (ULX ULY LRX LRY): " << fixed << setprecision(6) << minULX << " " << maxULY << " " << maxLRX << " " << minLRY << endl;
528 if(ulx_opt[0]||uly_opt[0]||lrx_opt[0]||lry_opt[0]){
529 maxLRX=lrx_opt[0];
530 maxULY=uly_opt[0];
531 minULX=ulx_opt[0];
532 minLRY=lry_opt[0];
533 }
534
535 bool forceEUgrid=false;
536 if(projection_opt.size())
537 forceEUgrid=(!(projection_opt[0].compare("EPSG:3035"))||!(projection_opt[0].compare("EPSG:3035"))||projection_opt[0].find("ETRS-LAEA")!=string::npos);
538 if(forceEUgrid){
539 //force to LAEA grid
540 minULX=floor(minULX);
541 minULX-=static_cast<int>(minULX)%(static_cast<int>(dx));
542 maxULY=ceil(maxULY);
543 if(static_cast<int>(maxULY)%static_cast<int>(dy))
544 maxULY+=dy;
545 maxULY-=static_cast<int>(maxULY)%(static_cast<int>(dy));
546 maxLRX=ceil(maxLRX);
547 if(static_cast<int>(maxLRX)%static_cast<int>(dx))
548 maxLRX+=dx;
549 maxLRX-=static_cast<int>(maxLRX)%(static_cast<int>(dx));
550 minLRY=floor(minLRY);
551 minLRY-=static_cast<int>(minLRY)%(static_cast<int>(dy));
552 }
553 else if(align_opt[0]){
554 if(minULX>imgReader[0].getUlx())
555 minULX-=fmod(minULX-imgReader[0].getUlx(),dx);
556 else if(minULX<imgReader[0].getUlx())
557 minULX+=fmod(imgReader[0].getUlx()-minULX,dx)-dx;
558 if(maxLRX<imgReader[0].getLrx())
559 maxLRX+=fmod(imgReader[0].getLrx()-maxLRX,dx);
560 else if(maxLRX>imgReader[0].getLrx())
561 maxLRX-=fmod(maxLRX-imgReader[0].getLrx(),dx)+dx;
562 if(minLRY>imgReader[0].getLry())
563 minLRY-=fmod(minLRY-imgReader[0].getLry(),dy);
564 else if(minLRY<imgReader[0].getLry())
565 minLRY+=fmod(imgReader[0].getLry()-minLRY,dy)-dy;
566 if(maxULY<imgReader[0].getUly())
567 maxULY+=fmod(imgReader[0].getUly()-maxULY,dy);
568 else if(maxULY>imgReader[0].getUly())
569 maxULY-=fmod(maxULY-imgReader[0].getUly(),dy)+dy;
570 }
571
572 if(verbose_opt[0])
573 cout << "bounding box composite image (ULX ULY LRX LRY): " << fixed << setprecision(6) << minULX << " " << maxULY << " " << maxLRX << " " << minLRY << endl;
574 //initialize image
575 if(verbose_opt[0])
576 cout << "initializing composite image..." << endl;
577 // double dcol=(maxLRX-minULX+dx-1)/dx;
578 // double drow=(maxULY-minLRY+dy-1)/dy;
579 // int ncol=static_cast<int>(dcol);
580 // int nrow=static_cast<int>(drow);
581
582 int ncol=abs(static_cast<int>(ceil((maxLRX-minULX)/dx)));
583 int nrow=abs(static_cast<int>(ceil((maxULY-minLRY)/dy)));
584 // int ncol=ceil((maxLRX-minULX)/dx);
585 // int nrow=ceil((maxULY-minLRY)/dy);
586 if(verbose_opt[0])
587 cout << "composite image dim (nrow x ncol): " << nrow << " x " << ncol << endl;
588 ImgWriterGdal imgWriter;
589 while(weight_opt.size()<input_opt.size())
590 weight_opt.push_back(weight_opt[0]);
591 if(verbose_opt[0]){
592 std::cout << weight_opt << std::endl;
593 }
594 if(cruleMap[crule_opt[0]]==crule::mode){
595 nwriteBand=(file_opt[0])? class_opt.size()+1:class_opt.size();
596 }
597 else
598 nwriteBand=(file_opt[0])? bands.size()+1:bands.size();
599 if(output_opt.empty()){
600 std::cerr << "No output file provided (use option -o). Use --help for help information" << std::endl;
601 exit(0);
602 }
603 if(verbose_opt[0])
604 cout << "open output image " << output_opt[0] << " with " << nwriteBand << " bands" << endl << flush;
605
606 try{
607 imgWriter.open(output_opt[0],ncol,nrow,nwriteBand,theType,imageType,option_opt);
608 imgWriter.setNoData(dstnodata_opt);
609 }
610 catch(string error){
611 cout << error << endl;
612 }
613 if(description_opt.size())
614 imgWriter.setImageDescription(description_opt[0]);
615 double gt[6];
616 gt[0]=minULX;
617 gt[1]=dx;
618 gt[2]=0;
619 gt[3]=maxULY;
620 gt[4]=0;
621 gt[5]=-dy;
622 imgWriter.setGeoTransform(gt);
623 // imgWriter.setGeoTransform(minULX,maxULY,dx,dy,0,0);
624 if(projection_opt.size()){
625 if(verbose_opt[0])
626 cout << "projection: " << projection_opt[0] << endl;
627 imgWriter.setProjectionProj4(projection_opt[0]);
628 }
629 else if(theProjection!=""){
630 if(verbose_opt[0])
631 cout << "projection: " << theProjection << endl;
632 imgWriter.setProjection(theProjection);
633 }
634 if(imgWriter.getDataType()==GDT_Byte){
635 if(colorTable_opt.size()){
636 if(colorTable_opt[0]!="none")
637 imgWriter.setColorTable(colorTable_opt[0]);
638 }
639 else if(theColorTable)
640 imgWriter.setColorTable(theColorTable);
641 }
642
643 ImgWriterGdal maskWriter;
644 if(extent_opt.size()&&(cut_opt[0]||eoption_opt.size())){
645 try{
646 maskWriter.open("/vsimem/mask.tif",ncol,nrow,1,GDT_Float32,"GTiff",option_opt);
647 double gt[6];
648 gt[0]=minULX;
649 gt[1]=dx;
650 gt[2]=0;
651 gt[3]=maxULY;
652 gt[4]=0;
653 gt[5]=-dy;
654 maskWriter.setGeoTransform(gt);
655 if(projection_opt.size())
656 maskWriter.setProjectionProj4(projection_opt[0]);
657 else if(theProjection!=""){
658 if(verbose_opt[0])
659 cout << "projection: " << theProjection << endl;
660 maskWriter.setProjection(theProjection);
661 }
662 vector<double> burnValues(1,1);//burn value is 1 (single band)
663 maskWriter.rasterizeOgr(extentReader,burnValues,eoption_opt);
664 maskWriter.close();
665 }
666 catch(string error){
667 cerr << error << std::endl;
668 exit(2);
669 }
670 catch(...){
671 cerr << "error caught" << std::endl;
672 exit(1);
673 }
674 //todo: support multiple masks
675 mask_opt.clear();
676 mask_opt.push_back("/vsimem/mask.tif");
677 }
678 ImgReaderGdal maskReader;
679 if(mask_opt.size()){
680 try{
681 if(verbose_opt[0]>=1)
682 std::cout << "opening mask image file " << mask_opt[0] << std::endl;
683 maskReader.open(mask_opt[0],GA_ReadOnly);
684 if(mskband_opt[0]>=maskReader.nrOfBand()){
685 string errorString="Error: illegal mask band";
686 throw(errorString);
687 }
688 }
689 catch(string error){
690 cerr << error << std::endl;
691 exit(2);
692 }
693 catch(...){
694 cerr << "error caught" << std::endl;
695 exit(1);
696 }
697 }
698
699 //create composite image
700 if(verbose_opt[0])
701 cout << "creating composite image" << endl;
702 Vector2d<double> writeBuffer(nband,imgWriter.nrOfCol());
703 vector<short> fileBuffer(ncol);//holds the number of used files
704 Vector2d<short> maxBuffer;//buffer used for maximum voting
705 // Vector2d<double> readBuffer(nband);
706 vector<Vector2d<double> > readBuffer(input_opt.size());
707 for(int ifile=0;ifile<input_opt.size();++ifile)
708 readBuffer[ifile].resize(imgReader[ifile].nrOfBand());
710 if(cruleMap[crule_opt[0]]==crule::maxndvi)//ndvi
711 assert(ruleBand_opt.size()==2);
712 if(cruleMap[crule_opt[0]]==crule::mode){//max voting
713 maxBuffer.resize(imgWriter.nrOfCol(),256);//use only byte images for max voting
714 for(int iclass=0;iclass<class_opt.size();++iclass)
715 assert(class_opt[iclass]<maxBuffer.size());
716 }
717 int jb=0;
718 double readRow=0;
719 double readCol=0;
720 double lowerCol=0;
721 double upperCol=0;
722 const char* pszMessage;
723 void* pProgressArg=NULL;
724 GDALProgressFunc pfnProgress=GDALTermProgress;
725 double progress=0;
726 pfnProgress(progress,pszMessage,pProgressArg);
727 for(int irow=0;irow<imgWriter.nrOfRow();++irow){
728 vector<float> lineMask;
729 Vector2d< vector<double> > storeBuffer;
730 vector<bool> writeValid(ncol);
731
732 //convert irow to geo
733 double x=0;
734 double y=0;
735 imgWriter.image2geo(0,irow,x,y);
736
737
738 if(cruleMap[crule_opt[0]]==crule::mean ||
739 cruleMap[crule_opt[0]]==crule::median ||
740 cruleMap[crule_opt[0]]==crule::sum ||
741 cruleMap[crule_opt[0]]==crule::minallbands ||
742 cruleMap[crule_opt[0]]==crule::maxallbands ||
743 cruleMap[crule_opt[0]]==crule::stdev)
744 storeBuffer.resize(nband,ncol);
745 for(int icol=0;icol<imgWriter.nrOfCol();++icol){
746 writeValid[icol]=false;
747 fileBuffer[icol]=0;
748 if(cruleMap[crule_opt[0]]==crule::mode){//max voting
749 for(int iclass=0;iclass<256;++iclass)
750 maxBuffer[icol][iclass]=0;
751 }
752 else{
753 for(int iband=0;iband<nband;++iband)
754 writeBuffer[iband][icol]=dstnodata_opt[0];
755 }
756 }
757
758 double oldRowMask=-1;//keep track of row mask to optimize number of line readings
759
760 for(int ifile=0;ifile<input_opt.size();++ifile){
761 //imgReader already open...
762 // try{
763 // imgReader.open(input_opt[ifile]);
764 // }
765 // catch(string error){
766 // cout << error << endl;
767 // }
768 // assert(imgReader.getDataType()==theType);
769 assert(imgReader[ifile].nrOfBand()>=nband);
770 if(!imgReader[ifile].covers(minULX,maxULY,maxLRX,minLRY)){
771 // imgReader.close();
772 continue;
773 }
774 double uli,ulj,lri,lrj;
775 imgReader[ifile].geo2image(minULX+(magic_x-1.0)*imgReader[ifile].getDeltaX(),maxULY-(magic_y-1.0)*imgReader[ifile].getDeltaY(),uli,ulj);
776 imgReader[ifile].geo2image(maxLRX+(magic_x-2.0)*imgReader[ifile].getDeltaX(),minLRY-(magic_y-2.0)*imgReader[ifile].getDeltaY(),lri,lrj);
777 uli=floor(uli);
778 ulj=floor(ulj);
779 lri=floor(lri);
780 lrj=floor(lrj);
781 double startCol=uli;
782 double endCol=lri;
783 if(uli<0)
784 startCol=0;
785 else if(uli>=imgReader[ifile].nrOfCol())
786 startCol=imgReader[ifile].nrOfCol()-1;
787 if(lri<0)
788 endCol=0;
789 else if(lri>=imgReader[ifile].nrOfCol())
790 endCol=imgReader[ifile].nrOfCol()-1;
791 // int readncol=endCol-startCol+1;
792
793 //lookup corresponding row for irow in this file
794 imgReader[ifile].geo2image(x,y,readCol,readRow);
795 if(readRow<0||readRow>=imgReader[ifile].nrOfRow()){
796 // imgReader.close();
797 continue;
798 }
799 // for(int iband=0;iband<imgReader.nrOfBand();++iband){
800 for(int iband=0;iband<nband;++iband){
801 int readBand=(band_opt.size()>iband)? band_opt[iband] : iband;
802 // readBuffer[iband].resize(readncol);
803 try{
804 imgReader[ifile].readData(readBuffer[ifile][iband],startCol,endCol,readRow,readBand,theResample);
805 //test
806 // imgReader[ifile].readData(readBuffer[ifile][iband],static_cast<int>(startCol),static_cast<int>(endCol),static_cast<int>(readRow),static_cast<int>(readBand));
807 // if(readRow==0&&iband==0){
808 // for(int icol=0;icol<10;++icol)
809 // cout << readBuffer[0][0][icol] << " ";
810 // cout << endl;
811 // }
812 }
813 catch(string error){
814 cerr << "error reading image " << input_opt[ifile] << ": " << endl;
815 throw;
816 }
817 }
818 for(int ib=0;ib<ncol;++ib){
819 imgWriter.image2geo(ib,irow,x,y);
820 //check mask first
821 bool valid=true;
822 if(mask_opt.size()){
823 //read mask
824 double colMask=0;
825 double rowMask=0;
826
827 maskReader.geo2image(x,y,colMask,rowMask);
828 colMask=static_cast<int>(colMask);
829 rowMask=static_cast<int>(rowMask);
830 if(rowMask>=0&&rowMask<maskReader.nrOfRow()&&colMask>=0&&colMask<maskReader.nrOfCol()){
831 if(static_cast<int>(rowMask)!=static_cast<int>(oldRowMask)){
832
833 assert(rowMask>=0&&rowMask<maskReader.nrOfRow());
834 try{
835 maskReader.readData(lineMask,static_cast<int>(rowMask),mskband_opt[0]);
836 }
837 catch(string errorstring){
838 cerr << errorstring << endl;
839 exit(1);
840 }
841 catch(...){
842 cerr << "error caught" << std::endl;
843 exit(3);
844 }
845 oldRowMask=rowMask;
846 }
847 if(lineMask[colMask]==msknodata_opt[0])
848 valid=false;
849 }
850 }
851
852 if(!valid)
853 continue;
854
855 //lookup corresponding row for irow in this file
856 imgReader[ifile].geo2image(x,y,readCol,readRow);
857 if(readCol<0||readCol>=imgReader[ifile].nrOfCol())
858 continue;
859 double val_current=0;
860 double val_new=0;
861 bool readValid=true;
862 switch(theResample){
863 case(BILINEAR):
864 lowerCol=readCol-0.5;
865 lowerCol=static_cast<int>(lowerCol);
866 upperCol=readCol+0.5;
867 upperCol=static_cast<int>(upperCol);
868 if(lowerCol<0)
869 lowerCol=0;
870 if(upperCol>=imgReader[ifile].nrOfCol())
871 upperCol=imgReader[ifile].nrOfCol()-1;
872 for(int vband=0;vband<bndnodata_opt.size();++vband){
873 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][bndnodata_opt[vband]][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][bndnodata_opt[vband]][lowerCol-startCol];
874 if(minValue_opt.size()>vband){
875 if(val_new<=minValue_opt[vband]){
876 readValid=false;
877 break;
878 }
879 }
880 if(maxValue_opt.size()>vband){
881 if(val_new>=maxValue_opt[vband]){
882 readValid=false;
883 break;
884 }
885 }
886 if(srcnodata_opt.size()>vband){
887 if(val_new==srcnodata_opt[vband]){
888 readValid=false;
889 break;
890 }
891 }
892 }
893 break;
894 default:
895 readCol=static_cast<int>(readCol);
896 for(int vband=0;vband<bndnodata_opt.size();++vband){
897 val_new=readBuffer[ifile][bndnodata_opt[vband]][readCol-startCol];
898 if(minValue_opt.size()>vband){
899 if(val_new<=minValue_opt[vband]){
900 readValid=false;
901 break;
902 }
903 }
904 if(maxValue_opt.size()>vband){
905 if(val_new>=maxValue_opt[vband]){
906 readValid=false;
907 break;
908 }
909 }
910 if(srcnodata_opt.size()>vband){
911 if(val_new==srcnodata_opt[vband]){
912 readValid=false;
913 break;
914 }
915 }
916 }
917 break;
918 }
919 if(readValid){
920 if(file_opt[0]==1)
921 ++fileBuffer[ib];
922 if(writeValid[ib]){
923 int iband=0;
924 switch(cruleMap[crule_opt[0]]){
925 case(crule::maxndvi):{//max ndvi
926 double red_current=writeBuffer[ruleBand_opt[0]][ib];
927 double nir_current=writeBuffer[ruleBand_opt[1]][ib];
928 double ndvi_current=0;
929 if(red_current+nir_current>0&&red_current>=0&&nir_current>=0)
930 ndvi_current=(nir_current-red_current)/(nir_current+red_current);
931 double ndvi_new=0;
932 double red_new=0;
933 double nir_new=0;
934 switch(theResample){
935 case(BILINEAR):
936 lowerCol=readCol-0.5;
937 lowerCol=static_cast<int>(lowerCol);
938 upperCol=readCol+0.5;
939 upperCol=static_cast<int>(upperCol);
940 if(lowerCol<0)
941 lowerCol=0;
942 if(upperCol>=imgReader[ifile].nrOfCol())
943 upperCol=imgReader[ifile].nrOfCol()-1;
944 red_new=(readCol-0.5-lowerCol)*readBuffer[ifile][ruleBand_opt[0]][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][ruleBand_opt[0]][lowerCol-startCol];
945 nir_new=(readCol-0.5-lowerCol)*readBuffer[ifile][ruleBand_opt[1]][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][ruleBand_opt[1]][lowerCol-startCol];
946 if(red_new+nir_new>0&&red_new>=0&&nir_new>=0)
947 ndvi_new=(nir_new-red_new)/(nir_new+red_new);
948 if(ndvi_new>=ndvi_current){
949 for(iband=0;iband<nband;++iband){
950 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
951 writeBuffer[iband][ib]=val_new;
952 }
953 if(file_opt[0]>1)
954 fileBuffer[ib]=ifile;
955 }
956 break;
957 default:
958 readCol=static_cast<int>(readCol);
959 red_new=readBuffer[ifile][ruleBand_opt[0]][readCol-startCol];
960 nir_new=readBuffer[ifile][ruleBand_opt[1]][readCol-startCol];
961 if(red_new+nir_new>0&&red_new>=0&&nir_new>=0)
962 ndvi_new=(nir_new-red_new)/(nir_new+red_new);
963 if(ndvi_new>=ndvi_current){
964 for(iband=0;iband<nband;++iband){
965 val_new=readBuffer[ifile][iband][readCol-startCol];
966 writeBuffer[iband][ib]=val_new;
967 }
968 if(file_opt[0]>1)
969 fileBuffer[ib]=ifile;
970 }
971 break;
972 }
973 break;
974 }
975 case(crule::maxband):
976 case(crule::minband):
977 case(crule::validband)://max,min,valid band
978 val_current=writeBuffer[ruleBand_opt[0]][ib];
979 switch(theResample){
980 case(BILINEAR):
981 lowerCol=readCol-0.5;
982 lowerCol=static_cast<int>(lowerCol);
983 upperCol=readCol+0.5;
984 upperCol=static_cast<int>(upperCol);
985 if(lowerCol<0)
986 lowerCol=0;
987 if(upperCol>=imgReader[ifile].nrOfCol())
988 upperCol=imgReader[ifile].nrOfCol()-1;
989 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][ruleBand_opt[0]][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][ruleBand_opt[0]][lowerCol-startCol];
990 val_new*=weight_opt[ifile];
991 if((cruleMap[crule_opt[0]]==crule::maxband&&val_new>val_current)||(cruleMap[crule_opt[0]]==crule::minband&&val_new<val_current)||(cruleMap[crule_opt[0]]==crule::validband)){//&&val_new>minValue_opt[0]&&val_new<maxValue_opt[0])){
992 for(iband=0;iband<nband;++iband){
993 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
994 val_new*=weight_opt[ifile];
995 writeBuffer[iband][ib]=val_new;
996 }
997 if(file_opt[0]>1)
998 fileBuffer[ib]=ifile;
999 }
1000 break;
1001 default:
1002 readCol=static_cast<int>(readCol);
1003 val_new=readBuffer[ifile][ruleBand_opt[0]][readCol-startCol];
1004 val_new*=weight_opt[ifile];
1005 if((cruleMap[crule_opt[0]]==crule::maxband&&val_new>val_current)||(cruleMap[crule_opt[0]]==crule::minband&&val_new<val_current)||(cruleMap[crule_opt[0]]==crule::validband)){//&&val_new>minValue_opt[0]&&val_new<maxValue_opt[0])){
1006 for(iband=0;iband<nband;++iband){
1007 val_new=readBuffer[ifile][iband][readCol-startCol];
1008 val_new*=weight_opt[ifile];
1009 writeBuffer[iband][ib]=val_new;
1010 }
1011 if(file_opt[0]>1)
1012 fileBuffer[ib]=ifile;
1013 }
1014 break;
1015 }
1016 break;
1017 case(crule::mode)://max voting (only for Byte images)
1018 switch(theResample){
1019 case(BILINEAR):
1020 lowerCol=readCol-0.5;
1021 lowerCol=static_cast<int>(lowerCol);
1022 upperCol=readCol+0.5;
1023 upperCol=static_cast<int>(upperCol);
1024 if(lowerCol<0)
1025 lowerCol=0;
1026 if(upperCol>=imgReader[ifile].nrOfCol())
1027 upperCol=imgReader[ifile].nrOfCol()-1;
1028 for(iband=0;iband<nband;++iband){
1029 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1030 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1031 // ++(maxBuffer[ib][val_new]);
1032 }
1033 break;
1034 default:
1035 readCol=static_cast<int>(readCol);
1036 for(iband=0;iband<nband;++iband){
1037 val_new=readBuffer[ifile][iband][readCol-startCol];
1038 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1039 }
1040 break;
1041 }
1042 break;
1043 case(crule::mean)://mean value
1044 case(crule::median)://median value
1045 case(crule::sum)://sum value
1046 case(crule::minallbands)://minimum for each and every band
1047 case(crule::maxallbands)://maximum for each and every band
1048 case(crule::stdev)://maximum for each and every band
1049 switch(theResample){
1050 case(BILINEAR):
1051 lowerCol=readCol-0.5;
1052 lowerCol=static_cast<int>(lowerCol);
1053 upperCol=readCol+0.5;
1054 upperCol=static_cast<int>(upperCol);
1055 if(lowerCol<0)
1056 lowerCol=0;
1057 if(upperCol>=imgReader[ifile].nrOfCol())
1058 upperCol=imgReader[ifile].nrOfCol()-1;
1059 for(iband=0;iband<nband;++iband){
1060 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1061 val_new*=weight_opt[ifile];
1062 storeBuffer[iband][ib].push_back(val_new);
1063 }
1064 break;
1065 default:
1066 readCol=static_cast<int>(readCol);
1067 for(iband=0;iband<nband;++iband){
1068 val_new=readBuffer[ifile][iband][readCol-startCol];
1069 val_new*=weight_opt[ifile];
1070 storeBuffer[iband][ib].push_back(val_new);
1071 assert(ifile>0);
1072 // assert(weight_opt[ifile]>=0);
1073 // assert(storeBuffer[iband][ib].back()>=0);
1074 }
1075 break;
1076 }
1077 if(file_opt[0]>1)
1078 fileBuffer[ib]=ifile;
1079 break;
1080 case(crule::overwrite):
1081 default:
1082 switch(theResample){
1083 case(BILINEAR):
1084 lowerCol=readCol-0.5;
1085 lowerCol=static_cast<int>(lowerCol);
1086 upperCol=readCol+0.5;
1087 upperCol=static_cast<int>(upperCol);
1088 if(lowerCol<0)
1089 lowerCol=0;
1090 if(upperCol>=imgReader[ifile].nrOfCol())
1091 upperCol=imgReader[ifile].nrOfCol()-1;
1092 for(iband=0;iband<nband;++iband){
1093 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1094 val_new*=weight_opt[ifile];
1095 writeBuffer[iband][ib]=val_new;
1096 }
1097 break;
1098 default:
1099 readCol=static_cast<int>(readCol);
1100 for(iband=0;iband<nband;++iband){
1101 val_new=readBuffer[ifile][iband][readCol-startCol];
1102 val_new*=weight_opt[ifile];
1103 writeBuffer[iband][ib]=val_new;
1104 }
1105 break;
1106 }
1107 if(file_opt[0]>1)
1108 fileBuffer[ib]=ifile;
1109 break;
1110 }
1111 }
1112 else{
1113 // //test
1114 // if(readCol-startCol==0)
1115 // std::cout << "val_new(" << ib << "): " << val_new << std::endl;
1116 // else if(readCol-startCol==ncol-1)
1117 // std::cout << "val_new(" << ib << "): " << val_new << std::endl;
1118 writeValid[ib]=true;//readValid was true
1119 int iband=0;
1120 switch(cruleMap[crule_opt[0]]){
1121 case(crule::mean):
1122 case(crule::median):
1123 case(crule::sum):
1124 case(crule::minallbands):
1125 case(crule::maxallbands):
1126 case(crule::stdev):
1127 switch(theResample){
1128 case(BILINEAR):
1129 lowerCol=readCol-0.5;
1130 lowerCol=static_cast<int>(lowerCol);
1131 upperCol=readCol+0.5;
1132 upperCol=static_cast<int>(upperCol);
1133 if(lowerCol<0)
1134 lowerCol=0;
1135 if(upperCol>=imgReader[ifile].nrOfCol())
1136 upperCol=imgReader[ifile].nrOfCol()-1;
1137 for(iband=0;iband<nband;++iband){
1138 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1139 val_new*=weight_opt[ifile];
1140 storeBuffer[iband][ib].push_back(val_new);
1141 }
1142 break;
1143 default:
1144 readCol=static_cast<int>(readCol);
1145 for(iband=0;iband<nband;++iband){
1146 val_new=readBuffer[ifile][iband][readCol-startCol];
1147 val_new*=weight_opt[ifile];
1148 storeBuffer[iband][ib].push_back(val_new);
1149 }
1150 break;
1151 }
1152 if(file_opt[0]>1)
1153 fileBuffer[ib]=ifile;
1154 break;
1155 case(crule::mode):
1156 switch(theResample){
1157 case(BILINEAR):
1158 lowerCol=readCol-0.5;
1159 lowerCol=static_cast<int>(lowerCol);
1160 upperCol=readCol+0.5;
1161 upperCol=static_cast<int>(upperCol);
1162 if(lowerCol<0)
1163 lowerCol=0;
1164 if(upperCol>=imgReader[ifile].nrOfCol())
1165 upperCol=imgReader[ifile].nrOfCol()-1;
1166 for(iband=0;iband<nband;++iband){
1167 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1168 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1169 // ++(maxBuffer[ib][val_new]);
1170 }
1171 break;
1172 default:
1173 readCol=static_cast<int>(readCol);
1174 for(iband=0;iband<nband;++iband){
1175 val_new=readBuffer[ifile][iband][readCol-startCol];
1176 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1177 }
1178 // ++(maxBuffer[ib][val_new]);
1179 break;
1180 }
1181 break;
1182 default:
1183 switch(theResample){
1184 case(BILINEAR):
1185 lowerCol=readCol-0.5;
1186 lowerCol=static_cast<int>(lowerCol);
1187 upperCol=readCol+0.5;
1188 upperCol=static_cast<int>(upperCol);
1189 if(lowerCol<0)
1190 lowerCol=0;
1191 if(upperCol>=imgReader[ifile].nrOfCol())
1192 upperCol=imgReader[ifile].nrOfCol()-1;
1193 for(iband=0;iband<nband;++iband){
1194 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1195 val_new*=weight_opt[ifile];
1196 writeBuffer[iband][ib]=val_new;
1197 }
1198 break;
1199 default:
1200 readCol=static_cast<int>(readCol);
1201 for(iband=0;iband<nband;++iband){
1202 val_new=readBuffer[ifile][iband][readCol-startCol];
1203 val_new*=weight_opt[ifile];
1204 writeBuffer[iband][ib]=val_new;
1205 }
1206 break;
1207 }
1208 if(file_opt[0]>1)
1209 fileBuffer[ib]=ifile;
1210 break;
1211 }
1212 }
1213 }
1214 }
1215 // imgReader.close();
1216 }
1217 if(cruleMap[crule_opt[0]]==crule::mode){
1218 vector<short> classBuffer(imgWriter.nrOfCol());
1219 if(class_opt.size()>1){
1220 for(int iclass=0;iclass<class_opt.size();++iclass){
1221 for(int icol=0;icol<imgWriter.nrOfCol();++icol)
1222 classBuffer[icol]=maxBuffer[icol][class_opt[iclass]];
1223 try{
1224 imgWriter.writeData(classBuffer,irow,iclass);
1225 }
1226 catch(string error){
1227 cerr << "error writing image file " << output_opt[0] << ": " << error << endl;
1228 throw;
1229 }
1230 }
1231 }
1232 else{
1233 for(int icol=0;icol<imgWriter.nrOfCol();++icol){
1234 vector<short>::iterator maxit=maxBuffer[icol].begin();
1235 maxit=stat.mymax(maxBuffer[icol],maxBuffer[icol].begin(),maxBuffer[icol].end());
1236 writeBuffer[0][icol]=distance(maxBuffer[icol].begin(),maxit);
1237 if(file_opt[0]>1)
1238 fileBuffer[icol]=*(maxit);
1239 }
1240 try{
1241 imgWriter.writeData(writeBuffer[0],irow,0);
1242 if(file_opt[0])
1243 imgWriter.writeData(fileBuffer,irow,1);
1244 }
1245 catch(string error){
1246 cerr << "error writing image file " << output_opt[0] << ": " << error << endl;
1247 throw;
1248 }
1249 }
1250 }
1251 else{
1252 for(int iband=0;iband<bands.size();++iband){
1253 // assert(writeBuffer[bands[iband]].size()==imgWriter.nrOfCol());
1254 assert(writeBuffer[iband].size()==imgWriter.nrOfCol());
1255 for(int icol=0;icol<imgWriter.nrOfCol();++icol){
1256 try{
1257 switch(cruleMap[crule_opt[0]]){
1258 case(crule::mean):
1259 // writeBuffer[iband][icol]=stat.mean(storeBuffer[bands[iband]][icol]);
1260 writeBuffer[iband][icol]=stat.mean(storeBuffer[iband][icol]);
1261 break;
1262 case(crule::median):
1263 // writeBuffer[iband][icol]=stat.median(storeBuffer[bands[iband]][icol]);
1264 writeBuffer[iband][icol]=stat.median(storeBuffer[iband][icol]);
1265 break;
1266 case(crule::sum):
1267 // writeBuffer[iband][icol]=stat.sum(storeBuffer[bands[iband]][icol]);
1268 writeBuffer[iband][icol]=stat.sum(storeBuffer[iband][icol]);
1269 break;
1270 case(crule::minallbands):
1271 // writeBuffer[iband][icol]=stat.mymin(storeBuffer[bands[iband]][icol]);
1272 writeBuffer[iband][icol]=stat.mymin(storeBuffer[iband][icol]);
1273 break;
1274 case(crule::maxallbands):
1275 // writeBuffer[iband][icol]=stat.mymax(storeBuffer[bands[iband]][icol]);
1276 writeBuffer[iband][icol]=stat.mymax(storeBuffer[iband][icol]);
1277 break;
1278 case(crule::stdev):
1279 // writeBuffer[iband][icol]=sqrt(stat.var(storeBuffer[bands[iband]][icol]));
1280 writeBuffer[iband][icol]=sqrt(stat.var(storeBuffer[iband][icol]));
1281 break;
1282 default:
1283 break;
1284 }
1285 }
1286 catch(string error){
1287 if(verbose_opt[0])
1288 cerr << error << endl;
1289 writeBuffer[iband][icol]=dstnodata_opt[0];
1290 continue;
1291 }
1292 }
1293 try{
1294 imgWriter.writeData(writeBuffer[iband],irow,iband);
1295 }
1296 catch(string error){
1297 cerr << error << " in " << output_opt[0] << endl;
1298 throw;
1299 }
1300 }
1301 if(file_opt[0]){
1302 try{
1303 imgWriter.writeData(fileBuffer,irow,bands.size());
1304 }
1305 catch(string error){
1306 cerr << error << " in " << output_opt[0] << endl;
1307 throw;
1308 }
1309 }
1310 }
1311 progress=static_cast<float>(irow+1.0)/imgWriter.nrOfRow();
1312 pfnProgress(progress,pszMessage,pProgressArg);
1313 }
1314 if(extent_opt.size()&&(cut_opt[0]||eoption_opt.size())){
1315 extentReader.close();
1316 }
1317 for(int ifile=0;ifile<input_opt.size();++ifile){
1318 imgReader[ifile].close();
1319 }
1320 if(mask_opt.size())
1321 maskReader.close();
1322 imgWriter.close();
1323}
int setNoData(const std::vector< double > nodata)
Set the no data values of this dataset using a standard template library (stl) vector as input.
int nrOfRow(void) const
Get the number of rows of this dataset.
bool geo2image(double x, double y, double &i, double &j) const
Convert georeferenced coordinates (x and y) to image coordinates (column and row)
CPLErr setGeoTransform(double *gt)
Set the geotransform data for this dataset.
int nrOfBand(void) const
Get the number of bands of this dataset.
CPLErr setProjectionProj4(const std::string &projection)
Set the projection for this dataset from user input (supports epsg:<number> format)
int nrOfCol(void) const
Get the number of columns of this dataset.
Definition: ImgRasterGdal.h:98
bool image2geo(double i, double j, double &x, double &y) const
Convert image coordinates (column and row) to georeferenced coordinates (x and y)
GDALDataType getDataType(int band=0) const
Get the GDAL datatype for this dataset.
CPLErr setProjection(const std::string &projection)
Set the projection for this dataset in well known text (wkt) format.
void readData(T &value, int col, int row, int band=0)
Read a single pixel cell value at a specific column and row for a specific band (all indices start co...
Definition: ImgReaderGdal.h:95
void close(void)
Set the memory (in MB) to cache a number of rows in memory.
void open(const std::string &filename, const GDALAccess &readMode=GA_ReadOnly)
Open an image.
void close(void)
Close the image.
void open(const std::string &filename, const ImgReaderGdal &imgSrc, const std::vector< std::string > &options=std::vector< std::string >())
Open an image for writing, copying image attributes from a source image. Image is directly written to...
void rasterizeOgr(ImgReaderOgr &ogrReader, const std::vector< double > &burnValues, const std::vector< std::string > &controlOptions=std::vector< std::string >(), const std::vector< std::string > &layernames=std::vector< std::string >())
Rasterize an OGR vector dataset using the gdal algorithm "GDALRasterizeLayers".
void setColorTable(const std::string &filename, int band=0)
Set the color table using an (ASCII) file with 5 columns (value R G B alpha)
void setImageDescription(const std::string &imageDescription)
Set the image description (only for GeoTiff format: TIFFTAG_IMAGEDESCRIPTION)
Definition: ImgWriterGdal.h:55
bool writeData(T &value, int col, int row, int band=0)
Write a single pixel cell value at a specific column and row for a specific band (all indices start c...
Definition: ImgWriterGdal.h:96