24 #include "imageclasses/ImgReaderGdal.h"
25 #include "imageclasses/ImgWriterGdal.h"
26 #include "imageclasses/ImgReaderOgr.h"
27 #include "base/Vector2d.h"
28 #include "base/Optionpk.h"
29 #include "algorithms/StatFactory.h"
136 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 int main(
int argc,
char *argv[])
143 Optionpk<string> input_opt(
"i",
"input",
"Input image file(s). If input contains multiple images, a multi-band output is created");
145 Optionpk<int> band_opt(
"b",
"band",
"band index(es) to crop (leave empty if all bands must be retained)");
146 Optionpk<double> dx_opt(
"dx",
"dx",
"Output resolution in x (in meter) (empty: keep original resolution)");
147 Optionpk<double> dy_opt(
"dy",
"dy",
"Output resolution in y (in meter) (empty: keep original resolution)");
148 Optionpk<string> extent_opt(
"e",
"extent",
"get boundary from extent from polygons in vector file");
149 Optionpk<bool> cut_opt(
"cut",
"crop_to_cutline",
"Crop the extent of the target dataset to the extent of the cutline.",
false);
150 Optionpk<string> mask_opt(
"m",
"mask",
"Use the first band of the specified file as a validity mask (0 is nodata).");
151 Optionpk<float> msknodata_opt(
"msknodata",
"msknodata",
"Mask value not to consider for composite.", 0);
152 Optionpk<short> mskband_opt(
"mskband",
"mskband",
"Mask band to read (0 indexed). Provide band for each mask.", 0);
153 Optionpk<double> ulx_opt(
"ulx",
"ulx",
"Upper left x value bounding box", 0.0);
154 Optionpk<double> uly_opt(
"uly",
"uly",
"Upper left y value bounding box", 0.0);
155 Optionpk<double> lrx_opt(
"lrx",
"lrx",
"Lower right x value bounding box", 0.0);
156 Optionpk<double> lry_opt(
"lry",
"lry",
"Lower right y value bounding box", 0.0);
157 Optionpk<string> crule_opt(
"cr",
"crule",
"Composite rule (overwrite, maxndvi, maxband, minband, mean, mode (only for byte images), median, sum, maxallbands, minallbands, stdev",
"overwrite");
158 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);
159 Optionpk<double> srcnodata_opt(
"srcnodata",
"srcnodata",
"invalid value(s) for input raster dataset");
160 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);
161 Optionpk<double> minValue_opt(
"min",
"min",
"flag values smaller or equal to this value as invalid.");
162 Optionpk<double> maxValue_opt(
"max",
"max",
"flag values larger or equal to this value as invalid.");
163 Optionpk<double> dstnodata_opt(
"dstnodata",
"dstnodata",
"nodata value to put in output raster dataset if not valid or out of bounds.", 0);
164 Optionpk<string> resample_opt(
"r",
"resampling-method",
"Resampling method (near: nearest neighbor, bilinear: bi-linear interpolation).",
"near");
165 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",
"");
166 Optionpk<string> oformat_opt(
"of",
"oformat",
"Output image format (see also gdal_translate).",
"GTiff");
167 Optionpk<string> option_opt(
"co",
"co",
"Creation option for output file. Multiple options can be specified.");
168 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");
169 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);
170 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);
171 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);
172 Optionpk<string> colorTable_opt(
"ct",
"ct",
"color table file with 5 columns: id R G B ALFA (0: transparent, 255: solid)");
173 Optionpk<string> description_opt(
"d",
"description",
"Set image description");
174 Optionpk<bool> align_opt(
"align",
"align",
"Align output bounding box to input image",
false);
177 extent_opt.setHide(1);
180 msknodata_opt.setHide(1);
181 mskband_opt.setHide(1);
182 option_opt.setHide(1);
184 weight_opt.setHide(1);
185 class_opt.setHide(1);
186 colorTable_opt.setHide(1);
187 description_opt.setHide(1);
191 doProcess=input_opt.retrieveOption(argc,argv);
192 output_opt.retrieveOption(argc,argv);
193 band_opt.retrieveOption(argc,argv);
194 dx_opt.retrieveOption(argc,argv);
195 dy_opt.retrieveOption(argc,argv);
196 extent_opt.retrieveOption(argc,argv);
197 cut_opt.retrieveOption(argc,argv);
198 mask_opt.retrieveOption(argc,argv);
199 msknodata_opt.retrieveOption(argc,argv);
200 mskband_opt.retrieveOption(argc,argv);
201 ulx_opt.retrieveOption(argc,argv);
202 uly_opt.retrieveOption(argc,argv);
203 lrx_opt.retrieveOption(argc,argv);
204 lry_opt.retrieveOption(argc,argv);
205 crule_opt.retrieveOption(argc,argv);
206 ruleBand_opt.retrieveOption(argc,argv);
207 srcnodata_opt.retrieveOption(argc,argv);
208 bndnodata_opt.retrieveOption(argc,argv);
209 minValue_opt.retrieveOption(argc,argv);
210 maxValue_opt.retrieveOption(argc,argv);
211 dstnodata_opt.retrieveOption(argc,argv);
212 resample_opt.retrieveOption(argc,argv);
213 otype_opt.retrieveOption(argc,argv);
214 oformat_opt.retrieveOption(argc,argv);
215 option_opt.retrieveOption(argc,argv);
216 projection_opt.retrieveOption(argc,argv);
217 file_opt.retrieveOption(argc,argv);
218 weight_opt.retrieveOption(argc,argv);
219 class_opt.retrieveOption(argc,argv);
220 colorTable_opt.retrieveOption(argc,argv);
221 description_opt.retrieveOption(argc,argv);
222 align_opt.retrieveOption(argc,argv);
223 verbose_opt.retrieveOption(argc,argv);
225 catch(
string predefinedString){
226 std::cout << predefinedString << std::endl;
231 cout <<
"Usage: pkcomposite -i input [-i input]* -o output" << endl;
233 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
237 std::map<std::string, crule::CRULE_TYPE> cruleMap;
241 cruleMap[
"overwrite"]=crule::overwrite;
242 cruleMap[
"maxndvi"]=crule::maxndvi;
243 cruleMap[
"maxband"]=crule::maxband;
244 cruleMap[
"minband"]=crule::minband;
245 cruleMap[
"validband"]=crule::validband;
246 cruleMap[
"mean"]=crule::mean;
247 cruleMap[
"mode"]=crule::mode;
248 cruleMap[
"median"]=crule::median;
249 cruleMap[
"sum"]=crule::sum;
250 cruleMap[
"maxallbands"]=crule::maxallbands;
251 cruleMap[
"minallbands"]=crule::minallbands;
252 cruleMap[
"stdev"]=crule::stdev;
254 if(srcnodata_opt.size()){
255 while(srcnodata_opt.size()<bndnodata_opt.size())
256 srcnodata_opt.push_back(srcnodata_opt[0]);
258 while(bndnodata_opt.size()<srcnodata_opt.size())
259 bndnodata_opt.push_back(bndnodata_opt[0]);
260 if(minValue_opt.size()){
261 while(minValue_opt.size()<bndnodata_opt.size())
262 minValue_opt.push_back(minValue_opt[0]);
263 while(bndnodata_opt.size()<minValue_opt.size())
264 bndnodata_opt.push_back(bndnodata_opt[0]);
266 if(maxValue_opt.size()){
267 while(maxValue_opt.size()<bndnodata_opt.size())
268 maxValue_opt.push_back(maxValue_opt[0]);
269 while(bndnodata_opt.size()<maxValue_opt.size())
270 bndnodata_opt.push_back(bndnodata_opt[0]);
272 RESAMPLE theResample;
273 if(resample_opt[0]==
"near"){
276 cout <<
"resampling: nearest neighbor" << endl;
278 else if(resample_opt[0]==
"bilinear"){
279 theResample=BILINEAR;
281 cout <<
"resampling: bilinear interpolation" << endl;
284 std::cout <<
"Error: resampling method " << resample_opt[0] <<
" not supported" << std::endl;
288 if(input_opt.empty()){
289 std::cerr <<
"No input file provided (use option -i). Use --help for help information" << std::endl;
302 double magic_x=1,magic_y=1;
304 GDALDataType theType=GDT_Unknown;
306 cout <<
"possible output data types: ";
307 for(
int iType = 0; iType < GDT_TypeCount; ++iType){
309 cout <<
" " << GDALGetDataTypeName((GDALDataType)iType);
310 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
311 && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
312 otype_opt[0].c_str()))
313 theType=(GDALDataType) iType;
317 if(theType==GDT_Unknown)
318 cout <<
"Unknown output pixel type: " << otype_opt[0] << endl;
320 cout <<
"Output pixel type: " << GDALGetDataTypeName(theType) << endl;
327 if(extent_opt.size()){
332 for(
int iextent=0;iextent<extent_opt.size();++iextent){
333 extentReader.open(extent_opt[iextent]);
334 if(!(extentReader.getExtent(e_ulx,e_uly,e_lrx,e_lry))){
335 cerr <<
"Error: could not get extent from " << extent_opt[0] << endl;
354 extentReader.close();
357 extentReader.open(extent_opt[0]);
361 cout <<
"--ulx=" << ulx_opt[0] <<
" --uly=" << uly_opt[0] <<
" --lrx=" << lrx_opt[0] <<
" --lry=" << lry_opt[0] << endl;
363 vector<ImgReaderGdal> imgReader(input_opt.size());
364 string theProjection=
"";
365 GDALColorTable* theColorTable=NULL;
368 for(
int ifile=0;ifile<input_opt.size();++ifile){
370 imgReader[ifile].open(input_opt[ifile]);
372 catch(
string errorstring){
373 cerr << errorstring <<
" " << input_opt[ifile] << endl;
377 if(colorTable_opt.empty())
378 if(imgReader[ifile].getColorTable())
379 theColorTable=(imgReader[ifile].getColorTable()->Clone());
380 if(projection_opt.empty())
381 theProjection=imgReader[ifile].getProjection();
382 if(option_opt.findSubstring(
"INTERLEAVE=")==option_opt.end()){
383 string theInterleave=
"INTERLEAVE=";
384 theInterleave+=imgReader[ifile].getInterleave();
385 option_opt.push_back(theInterleave);
388 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]))){
390 cout << input_opt[ifile] <<
" not within bounding box, skipping..." << endl;
394 double theULX, theULY, theLRX, theLRY;
395 imgReader[ifile].getBoundingBox(theULX,theULY,theLRX,theLRY);
397 cerr <<
"Error: " << input_opt[ifile] <<
" is not georeferenced, only referenced images are supported for pkcomposite " << endl;
401 cout <<
"Bounding Box (ULX ULY LRX LRY): " << fixed << setprecision(6) << theULX <<
" " << theULY <<
" " << theLRX <<
" " << theLRY << endl;
404 switch(cruleMap[crule_opt[0]]){
406 case(crule::overwrite):
407 cout <<
"Composite rule: overwrite" << endl;
409 case(crule::maxndvi):
410 cout <<
"Composite rule: max ndvi" << endl;
412 case(crule::maxband):
413 cout <<
"Composite rule: max band" << endl;
415 case(crule::minband):
416 cout <<
"Composite rule: min band" << endl;
418 case(crule::validband):
419 cout <<
"Composite rule: valid band" << endl;
422 cout <<
"Composite rule: mean value" << endl;
425 cout <<
"Composite rule: max voting (only for byte images)" << endl;
428 cout <<
"Composite rule: median" << endl;
431 cout <<
"Composite rule: stdev" << endl;
434 cout <<
"Composite rule: sum" << endl;
436 case(crule::minallbands):
437 cout <<
"Composite rule: minallbands" << endl;
439 case(crule::maxallbands):
440 cout <<
"Composite rule: maxallbands" << endl;
445 nband=band_opt.size();
446 bands.resize(band_opt.size());
447 for(
int iband=0;iband<band_opt.size();++iband){
448 bands[iband]=band_opt[iband];
449 assert(bands[iband]<imgReader[ifile].nrOfBand());
453 nband=imgReader[ifile].nrOfBand();
455 for(
int iband=0;iband<nband;++iband)
458 for(
int iband=0;iband<bndnodata_opt.size();++iband){
459 assert(bndnodata_opt[iband]>=0&&bndnodata_opt[iband]<nband);
462 if(theType==GDT_Unknown){
463 theType=imgReader[ifile].getDataType();
465 cout <<
"Using data type from input image: " << GDALGetDataTypeName(theType) << endl;
468 if(oformat_opt.size())
469 imageType=oformat_opt[0];
471 imageType=imgReader[ifile].getImageType();
475 cout <<
"type of data for " << input_opt[ifile] <<
": " << theType << endl;
476 cout <<
"nband: " << nband << endl;
486 dx=imgReader[ifile].getDeltaX();
490 dy=imgReader[ifile].getDeltaY();
504 maxLRX=(theLRX>maxLRX)?theLRX:maxLRX;
505 maxULY=(theULY>maxULY)?theULY:maxULY;
506 minULX=(theULX<minULX)?theULX:minULX;
507 minLRY=(theLRY<minLRY)?theLRY:minLRY;
512 cout <<
"bounding box input images (ULX ULY LRX LRY): " << fixed << setprecision(6) << minULX <<
" " << maxULY <<
" " << maxLRX <<
" " << minLRY << endl;
513 if(ulx_opt[0]||uly_opt[0]||lrx_opt[0]||lry_opt[0]){
520 bool forceEUgrid=
false;
521 if(projection_opt.size())
522 forceEUgrid=(!(projection_opt[0].compare(
"EPSG:3035"))||!(projection_opt[0].compare(
"EPSG:3035"))||projection_opt[0].find(
"ETRS-LAEA")!=string::npos);
525 minULX=floor(minULX);
526 minULX-=
static_cast<int>(minULX)%(static_cast<int>(dx));
528 if(static_cast<int>(maxULY)%static_cast<int>(dy))
530 maxULY-=
static_cast<int>(maxULY)%(static_cast<int>(dy));
532 if(static_cast<int>(maxLRX)%static_cast<int>(dx))
534 maxLRX-=
static_cast<int>(maxLRX)%(static_cast<int>(dx));
535 minLRY=floor(minLRY);
536 minLRY-=
static_cast<int>(minLRY)%(static_cast<int>(dy));
538 else if(align_opt[0]){
539 if(minULX>imgReader[0].getUlx())
540 minULX-=fmod(minULX-imgReader[0].getUlx(),dx);
541 else if(minULX<imgReader[0].getUlx())
542 minULX+=fmod(imgReader[0].getUlx()-minULX,dx)-dx;
543 if(maxLRX<imgReader[0].getLrx())
544 maxLRX+=fmod(imgReader[0].getLrx()-maxLRX,dx);
545 else if(maxLRX>imgReader[0].getLrx())
546 maxLRX-=fmod(maxLRX-imgReader[0].getLrx(),dx)+dx;
547 if(minLRY>imgReader[0].getLry())
548 minLRY-=fmod(minLRY-imgReader[0].getLry(),dy);
549 else if(minLRY<imgReader[0].getLry())
550 minLRY+=fmod(imgReader[0].getLry()-minLRY,dy)-dy;
551 if(maxULY<imgReader[0].getUly())
552 maxULY+=fmod(imgReader[0].getUly()-maxULY,dy);
553 else if(maxULY>imgReader[0].getUly())
554 maxULY-=fmod(maxULY-imgReader[0].getUly(),dy)+dy;
558 cout <<
"bounding box composite image (ULX ULY LRX LRY): " << fixed << setprecision(6) << minULX <<
" " << maxULY <<
" " << maxLRX <<
" " << minLRY << endl;
561 cout <<
"initializing composite image..." << endl;
567 int ncol=ceil((maxLRX-minULX)/dx);
568 int nrow=ceil((maxULY-minLRY)/dy);
571 cout <<
"composite image dim (nrow x ncol): " << nrow <<
" x " << ncol << endl;
573 while(weight_opt.size()<input_opt.size())
574 weight_opt.push_back(weight_opt[0]);
576 std::cout << weight_opt << std::endl;
578 if(cruleMap[crule_opt[0]]==crule::mode){
579 nwriteBand=(file_opt[0])? class_opt.size()+1:class_opt.size();
582 nwriteBand=(file_opt[0])? bands.size()+1:bands.size();
583 if(output_opt.empty()){
584 std::cerr <<
"No output file provided (use option -o). Use --help for help information" << std::endl;
588 cout <<
"open output image " << output_opt[0] <<
" with " << nwriteBand <<
" bands" << endl << flush;
590 imgWriter.open(output_opt[0],ncol,nrow,nwriteBand,theType,imageType,option_opt);
591 for(
int iband=0;iband<nwriteBand;++iband)
592 imgWriter.GDALSetNoDataValue(dstnodata_opt[0],iband);
595 cout << error << endl;
597 if(description_opt.size())
598 imgWriter.setImageDescription(description_opt[0]);
606 imgWriter.setGeoTransform(gt);
608 if(projection_opt.size()){
610 cout <<
"projection: " << projection_opt[0] << endl;
611 imgWriter.setProjectionProj4(projection_opt[0]);
613 else if(theProjection!=
""){
615 cout <<
"projection: " << theProjection << endl;
616 imgWriter.setProjection(theProjection);
618 if(imgWriter.getDataType()==GDT_Byte){
619 if(colorTable_opt.size()){
620 if(colorTable_opt[0]!=
"none")
621 imgWriter.setColorTable(colorTable_opt[0]);
623 else if(theColorTable)
624 imgWriter.setColorTable(theColorTable);
628 if(extent_opt.size()&&cut_opt[0]){
630 maskWriter.open(
"/vsimem/mask.tif",ncol,nrow,1,GDT_Float32,
"GTiff",option_opt);
638 maskWriter.setGeoTransform(gt);
639 if(projection_opt.size())
640 maskWriter.setProjectionProj4(projection_opt[0]);
641 else if(theProjection!=
""){
643 cout <<
"projection: " << theProjection << endl;
644 maskWriter.setProjection(theProjection);
648 vector<double> burnValues(1,1);
649 maskWriter.rasterizeOgr(extentReader,burnValues);
653 cerr << error << std::endl;
657 cerr <<
"error caught" << std::endl;
662 mask_opt.push_back(
"/vsimem/mask.tif");
667 if(verbose_opt[0]>=1)
668 std::cout <<
"opening mask image file " << mask_opt[0] << std::endl;
669 maskReader.open(mask_opt[0]);
670 if(mskband_opt[0]>=maskReader.nrOfBand()){
671 string errorString=
"Error: illegal mask band";
676 cerr << error << std::endl;
680 cerr <<
"error caught" << std::endl;
687 cout <<
"creating composite image" << endl;
689 vector<short> fileBuffer(ncol);
692 vector<Vector2d<double> > readBuffer(input_opt.size());
693 for(
int ifile=0;ifile<input_opt.size();++ifile)
694 readBuffer[ifile].resize(imgReader[ifile].nrOfBand());
696 if(cruleMap[crule_opt[0]]==crule::maxndvi)
697 assert(ruleBand_opt.size()==2);
698 if(cruleMap[crule_opt[0]]==crule::mode){
699 maxBuffer.resize(imgWriter.nrOfCol(),256);
700 for(
int iclass=0;iclass<class_opt.size();++iclass)
701 assert(class_opt[iclass]<maxBuffer.size());
708 const char* pszMessage;
709 void* pProgressArg=NULL;
710 GDALProgressFunc pfnProgress=GDALTermProgress;
712 pfnProgress(progress,pszMessage,pProgressArg);
713 for(
int irow=0;irow<imgWriter.nrOfRow();++irow){
714 vector<float> lineMask;
716 vector<bool> writeValid(ncol);
721 imgWriter.image2geo(0,irow,x,y);
724 if(cruleMap[crule_opt[0]]==crule::mean ||
725 cruleMap[crule_opt[0]]==crule::median ||
726 cruleMap[crule_opt[0]]==crule::sum ||
727 cruleMap[crule_opt[0]]==crule::minallbands ||
728 cruleMap[crule_opt[0]]==crule::maxallbands ||
729 cruleMap[crule_opt[0]]==crule::stdev)
730 storeBuffer.resize(nband,ncol);
731 for(
int icol=0;icol<imgWriter.nrOfCol();++icol){
732 writeValid[icol]=
false;
734 if(cruleMap[crule_opt[0]]==crule::mode){
735 for(
int iclass=0;iclass<256;++iclass)
736 maxBuffer[icol][iclass]=0;
739 for(
int iband=0;iband<nband;++iband)
740 writeBuffer[iband][icol]=dstnodata_opt[0];
744 double oldRowMask=-1;
746 for(
int ifile=0;ifile<input_opt.size();++ifile){
755 assert(imgReader[ifile].nrOfBand()>=nband);
756 if(!imgReader[ifile].covers(minULX,maxULY,maxLRX,minLRY)){
760 double uli,ulj,lri,lrj;
761 imgReader[ifile].geo2image(minULX+(magic_x-1.0)*imgReader[ifile].getDeltaX(),maxULY-(magic_y-1.0)*imgReader[ifile].getDeltaY(),uli,ulj);
762 imgReader[ifile].geo2image(maxLRX+(magic_x-2.0)*imgReader[ifile].getDeltaX(),minLRY-(magic_y-2.0)*imgReader[ifile].getDeltaY(),lri,lrj);
772 else if(uli>=imgReader[ifile].nrOfCol())
773 startCol=imgReader[ifile].nrOfCol()-1;
776 else if(lri>=imgReader[ifile].nrOfCol())
777 endCol=imgReader[ifile].nrOfCol()-1;
778 int readncol=endCol-startCol+1;
781 imgReader[ifile].geo2image(x,y,readCol,readRow);
782 if(readRow<0||readRow>=imgReader[ifile].nrOfRow()){
787 for(
int iband=0;iband<nband;++iband){
788 int readBand=(band_opt.size()>iband)? band_opt[iband] : iband;
791 imgReader[ifile].readData(readBuffer[ifile][iband],GDT_Float64,startCol,endCol,readRow,readBand,theResample);
794 cerr <<
"error reading image " << input_opt[ifile] <<
": " << endl;
799 for(
int ib=0;ib<ncol;++ib){
800 imgWriter.image2geo(ib,irow,x,y);
808 maskReader.geo2image(x,y,colMask,rowMask);
809 colMask=
static_cast<int>(colMask);
810 rowMask=
static_cast<int>(rowMask);
811 if(rowMask>=0&&rowMask<maskReader.nrOfRow()&&colMask>=0&&colMask<maskReader.nrOfCol()){
812 if(static_cast<int>(rowMask)!=
static_cast<int>(oldRowMask)){
814 assert(rowMask>=0&&rowMask<maskReader.nrOfRow());
816 maskReader.readData(lineMask,GDT_Float32,static_cast<int>(rowMask),mskband_opt[0]);
818 catch(
string errorstring){
819 cerr << errorstring << endl;
823 cerr <<
"error caught" << std::endl;
828 if(lineMask[colMask]==msknodata_opt[0])
837 imgReader[ifile].geo2image(x,y,readCol,readRow);
838 if(readCol<0||readCol>=imgReader[ifile].nrOfCol())
840 double val_current=0;
845 lowerCol=readCol-0.5;
846 lowerCol=
static_cast<int>(lowerCol);
847 upperCol=readCol+0.5;
848 upperCol=
static_cast<int>(upperCol);
851 if(upperCol>=imgReader[ifile].nrOfCol())
852 upperCol=imgReader[ifile].nrOfCol()-1;
853 for(
int vband=0;vband<bndnodata_opt.size();++vband){
854 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];
855 if(minValue_opt.size()>vband){
856 if(val_new<=minValue_opt[vband]){
861 if(maxValue_opt.size()>vband){
862 if(val_new>=maxValue_opt[vband]){
867 if(srcnodata_opt.size()>vband){
868 if(val_new==srcnodata_opt[vband]){
876 readCol=
static_cast<int>(readCol);
877 for(
int vband=0;vband<bndnodata_opt.size();++vband){
878 val_new=readBuffer[ifile][bndnodata_opt[vband]][readCol-startCol];
879 if(minValue_opt.size()>vband){
880 if(val_new<=minValue_opt[vband]){
885 if(maxValue_opt.size()>vband){
886 if(val_new>=maxValue_opt[vband]){
891 if(srcnodata_opt.size()>vband){
892 if(val_new==srcnodata_opt[vband]){
905 switch(cruleMap[crule_opt[0]]){
906 case(crule::maxndvi):{
907 double red_current=writeBuffer[ruleBand_opt[0]][ib];
908 double nir_current=writeBuffer[ruleBand_opt[1]][ib];
909 double ndvi_current=0;
910 if(red_current+nir_current>0&&red_current>=0&&nir_current>=0)
911 ndvi_current=(nir_current-red_current)/(nir_current+red_current);
917 lowerCol=readCol-0.5;
918 lowerCol=
static_cast<int>(lowerCol);
919 upperCol=readCol+0.5;
920 upperCol=
static_cast<int>(upperCol);
923 if(upperCol>=imgReader[ifile].nrOfCol())
924 upperCol=imgReader[ifile].nrOfCol()-1;
925 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];
926 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];
927 if(red_new+nir_new>0&&red_new>=0&&nir_new>=0)
928 ndvi_new=(nir_new-red_new)/(nir_new+red_new);
929 if(ndvi_new>=ndvi_current){
930 for(iband=0;iband<nband;++iband){
931 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
932 writeBuffer[iband][ib]=val_new;
935 fileBuffer[ib]=ifile;
939 readCol=
static_cast<int>(readCol);
940 red_new=readBuffer[ifile][ruleBand_opt[0]][readCol-startCol];
941 nir_new=readBuffer[ifile][ruleBand_opt[1]][readCol-startCol];
942 if(red_new+nir_new>0&&red_new>=0&&nir_new>=0)
943 ndvi_new=(nir_new-red_new)/(nir_new+red_new);
944 if(ndvi_new>=ndvi_current){
945 for(iband=0;iband<nband;++iband){
946 val_new=readBuffer[ifile][iband][readCol-startCol];
947 writeBuffer[iband][ib]=val_new;
950 fileBuffer[ib]=ifile;
956 case(crule::maxband):
957 case(crule::minband):
958 case(crule::validband):
959 val_current=writeBuffer[ruleBand_opt[0]][ib];
962 lowerCol=readCol-0.5;
963 lowerCol=
static_cast<int>(lowerCol);
964 upperCol=readCol+0.5;
965 upperCol=
static_cast<int>(upperCol);
968 if(upperCol>=imgReader[ifile].nrOfCol())
969 upperCol=imgReader[ifile].nrOfCol()-1;
970 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];
971 val_new*=weight_opt[ifile];
972 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)){
973 for(iband=0;iband<nband;++iband){
974 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
975 val_new*=weight_opt[ifile];
976 writeBuffer[iband][ib]=val_new;
979 fileBuffer[ib]=ifile;
983 readCol=
static_cast<int>(readCol);
984 val_new=readBuffer[ifile][ruleBand_opt[0]][readCol-startCol];
985 val_new*=weight_opt[ifile];
986 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)){
987 for(iband=0;iband<nband;++iband){
988 val_new=readBuffer[ifile][iband][readCol-startCol];
989 val_new*=weight_opt[ifile];
990 writeBuffer[iband][ib]=val_new;
993 fileBuffer[ib]=ifile;
1001 lowerCol=readCol-0.5;
1002 lowerCol=
static_cast<int>(lowerCol);
1003 upperCol=readCol+0.5;
1004 upperCol=
static_cast<int>(upperCol);
1007 if(upperCol>=imgReader[ifile].nrOfCol())
1008 upperCol=imgReader[ifile].nrOfCol()-1;
1009 for(iband=0;iband<nband;++iband){
1010 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1011 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1016 readCol=
static_cast<int>(readCol);
1017 for(iband=0;iband<nband;++iband){
1018 val_new=readBuffer[ifile][iband][readCol-startCol];
1019 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1025 case(crule::median):
1027 case(crule::minallbands):
1028 case(crule::maxallbands):
1030 switch(theResample){
1032 lowerCol=readCol-0.5;
1033 lowerCol=
static_cast<int>(lowerCol);
1034 upperCol=readCol+0.5;
1035 upperCol=
static_cast<int>(upperCol);
1038 if(upperCol>=imgReader[ifile].nrOfCol())
1039 upperCol=imgReader[ifile].nrOfCol()-1;
1040 for(iband=0;iband<nband;++iband){
1041 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1042 val_new*=weight_opt[ifile];
1043 storeBuffer[iband][ib].push_back(val_new);
1047 readCol=
static_cast<int>(readCol);
1048 for(iband=0;iband<nband;++iband){
1049 val_new=readBuffer[ifile][iband][readCol-startCol];
1050 val_new*=weight_opt[ifile];
1051 storeBuffer[iband][ib].push_back(val_new);
1059 fileBuffer[ib]=ifile;
1061 case(crule::overwrite):
1063 switch(theResample){
1065 lowerCol=readCol-0.5;
1066 lowerCol=
static_cast<int>(lowerCol);
1067 upperCol=readCol+0.5;
1068 upperCol=
static_cast<int>(upperCol);
1071 if(upperCol>=imgReader[ifile].nrOfCol())
1072 upperCol=imgReader[ifile].nrOfCol()-1;
1073 for(iband=0;iband<nband;++iband){
1074 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1075 val_new*=weight_opt[ifile];
1076 writeBuffer[iband][ib]=val_new;
1080 readCol=
static_cast<int>(readCol);
1081 for(iband=0;iband<nband;++iband){
1082 val_new=readBuffer[ifile][iband][readCol-startCol];
1083 val_new*=weight_opt[ifile];
1084 writeBuffer[iband][ib]=val_new;
1089 fileBuffer[ib]=ifile;
1094 writeValid[ib]=
true;
1096 switch(cruleMap[crule_opt[0]]){
1098 case(crule::median):
1100 case(crule::minallbands):
1101 case(crule::maxallbands):
1103 switch(theResample){
1105 lowerCol=readCol-0.5;
1106 lowerCol=
static_cast<int>(lowerCol);
1107 upperCol=readCol+0.5;
1108 upperCol=
static_cast<int>(upperCol);
1111 if(upperCol>=imgReader[ifile].nrOfCol())
1112 upperCol=imgReader[ifile].nrOfCol()-1;
1113 for(iband=0;iband<nband;++iband){
1114 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1115 val_new*=weight_opt[ifile];
1116 storeBuffer[iband][ib].push_back(val_new);
1120 readCol=
static_cast<int>(readCol);
1121 for(iband=0;iband<nband;++iband){
1122 val_new=readBuffer[ifile][iband][readCol-startCol];
1123 val_new*=weight_opt[ifile];
1124 storeBuffer[iband][ib].push_back(val_new);
1129 fileBuffer[ib]=ifile;
1132 switch(theResample){
1134 lowerCol=readCol-0.5;
1135 lowerCol=
static_cast<int>(lowerCol);
1136 upperCol=readCol+0.5;
1137 upperCol=
static_cast<int>(upperCol);
1140 if(upperCol>=imgReader[ifile].nrOfCol())
1141 upperCol=imgReader[ifile].nrOfCol()-1;
1142 for(iband=0;iband<nband;++iband){
1143 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1144 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1149 readCol=
static_cast<int>(readCol);
1150 for(iband=0;iband<nband;++iband){
1151 val_new=readBuffer[ifile][iband][readCol-startCol];
1152 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1159 switch(theResample){
1161 lowerCol=readCol-0.5;
1162 lowerCol=
static_cast<int>(lowerCol);
1163 upperCol=readCol+0.5;
1164 upperCol=
static_cast<int>(upperCol);
1167 if(upperCol>=imgReader[ifile].nrOfCol())
1168 upperCol=imgReader[ifile].nrOfCol()-1;
1169 for(iband=0;iband<nband;++iband){
1170 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1171 val_new*=weight_opt[ifile];
1172 writeBuffer[iband][ib]=val_new;
1176 readCol=
static_cast<int>(readCol);
1177 for(iband=0;iband<nband;++iband){
1178 val_new=readBuffer[ifile][iband][readCol-startCol];
1179 val_new*=weight_opt[ifile];
1180 writeBuffer[iband][ib]=val_new;
1185 fileBuffer[ib]=ifile;
1193 if(cruleMap[crule_opt[0]]==crule::mode){
1194 vector<short> classBuffer(imgWriter.nrOfCol());
1195 if(class_opt.size()>1){
1196 for(
int iclass=0;iclass<class_opt.size();++iclass){
1197 for(
int icol=0;icol<imgWriter.nrOfCol();++icol)
1198 classBuffer[icol]=maxBuffer[icol][class_opt[iclass]];
1200 imgWriter.writeData(classBuffer,GDT_Int16,irow,iclass);
1202 catch(
string error){
1203 cerr <<
"error writing image file " << output_opt[0] <<
": " << error << endl;
1209 for(
int icol=0;icol<imgWriter.nrOfCol();++icol){
1210 vector<short>::iterator maxit=maxBuffer[icol].begin();
1211 maxit=stat.mymax(maxBuffer[icol],maxBuffer[icol].begin(),maxBuffer[icol].end());
1212 writeBuffer[0][icol]=distance(maxBuffer[icol].begin(),maxit);
1214 fileBuffer[icol]=*(maxit);
1217 imgWriter.writeData(writeBuffer[0],GDT_Float64,irow,0);
1219 imgWriter.writeData(fileBuffer,GDT_Int16,irow,1);
1221 catch(
string error){
1222 cerr <<
"error writing image file " << output_opt[0] <<
": " << error << endl;
1228 for(
int iband=0;iband<bands.size();++iband){
1230 assert(writeBuffer[iband].size()==imgWriter.nrOfCol());
1231 for(
int icol=0;icol<imgWriter.nrOfCol();++icol){
1233 switch(cruleMap[crule_opt[0]]){
1236 writeBuffer[iband][icol]=stat.mean(storeBuffer[iband][icol]);
1238 case(crule::median):
1240 writeBuffer[iband][icol]=stat.median(storeBuffer[iband][icol]);
1244 writeBuffer[iband][icol]=stat.sum(storeBuffer[iband][icol]);
1246 case(crule::minallbands):
1248 writeBuffer[iband][icol]=stat.mymin(storeBuffer[iband][icol]);
1250 case(crule::maxallbands):
1252 writeBuffer[iband][icol]=stat.mymax(storeBuffer[iband][icol]);
1256 writeBuffer[iband][icol]=sqrt(stat.var(storeBuffer[iband][icol]));
1262 catch(
string error){
1264 cerr << error << endl;
1265 writeBuffer[iband][icol]=dstnodata_opt[0];
1270 imgWriter.writeData(writeBuffer[iband],GDT_Float64,irow,iband);
1272 catch(
string error){
1273 cerr << error <<
" in " << output_opt[0] << endl;
1279 imgWriter.writeData(fileBuffer,GDT_Int16,irow,bands.size());
1281 catch(
string error){
1282 cerr << error <<
" in " << output_opt[0] << endl;
1287 progress=
static_cast<float>(irow+1.0)/imgWriter.nrOfRow();
1288 pfnProgress(progress,pszMessage,pProgressArg);
1290 if(extent_opt.size()&&cut_opt.size()){
1291 extentReader.close();
1293 for(
int ifile=0;ifile<input_opt.size();++ifile)
1294 imgReader[ifile].close();