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"
116 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};
121 int main(
int argc,
char *argv[])
123 Optionpk<string> input_opt(
"i",
"input",
"Input image file(s). If input contains multiple images, a multi-band output is created");
125 Optionpk<int> band_opt(
"b",
"band",
"band index(es) to crop (leave empty if all bands must be retained)");
126 Optionpk<double> dx_opt(
"dx",
"dx",
"Output resolution in x (in meter) (empty: keep original resolution)");
127 Optionpk<double> dy_opt(
"dy",
"dy",
"Output resolution in y (in meter) (empty: keep original resolution)");
128 Optionpk<string> extent_opt(
"e",
"extent",
"get boundary from extent from polygons in vector file");
129 Optionpk<bool> cut_opt(
"cut",
"crop_to_cutline",
"Crop the extent of the target dataset to the extent of the cutline.",
false);
130 Optionpk<string> mask_opt(
"m",
"mask",
"Use the first band of the specified file as a validity mask (0 is nodata).");
131 Optionpk<float> msknodata_opt(
"msknodata",
"msknodata",
"Mask value not to consider for composite.", 0);
132 Optionpk<short> mskband_opt(
"mskband",
"mskband",
"Mask band to read (0 indexed). Provide band for each mask.", 0);
133 Optionpk<double> ulx_opt(
"ulx",
"ulx",
"Upper left x value bounding box", 0.0);
134 Optionpk<double> uly_opt(
"uly",
"uly",
"Upper left y value bounding box", 0.0);
135 Optionpk<double> lrx_opt(
"lrx",
"lrx",
"Lower right x value bounding box", 0.0);
136 Optionpk<double> lry_opt(
"lry",
"lry",
"Lower right y value bounding box", 0.0);
137 Optionpk<string> crule_opt(
"cr",
"crule",
"Composite rule (overwrite, maxndvi, maxband, minband, mean, mode (only for byte images), median, sum, maxallbands, minallbands, stdev",
"overwrite");
138 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);
139 Optionpk<double> srcnodata_opt(
"srcnodata",
"srcnodata",
"invalid value(s) for input raster dataset");
140 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);
141 Optionpk<double> minValue_opt(
"min",
"min",
"flag values smaller or equal to this value as invalid.");
142 Optionpk<double> maxValue_opt(
"max",
"max",
"flag values larger or equal to this value as invalid.");
143 Optionpk<double> dstnodata_opt(
"dstnodata",
"dstnodata",
"nodata value to put in output raster dataset if not valid or out of bounds.", 0);
144 Optionpk<string> resample_opt(
"r",
"resampling-method",
"Resampling method (near: nearest neighbor, bilinear: bi-linear interpolation).",
"near");
145 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",
"");
146 Optionpk<string> oformat_opt(
"of",
"oformat",
"Output image format (see also gdal_translate). Empty string: inherit from input image");
147 Optionpk<string> option_opt(
"co",
"co",
"Creation option for output file. Multiple options can be specified.");
148 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");
149 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);
150 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);
151 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);
152 Optionpk<string> colorTable_opt(
"ct",
"ct",
"color table file with 5 columns: id R G B ALFA (0: transparent, 255: solid)");
153 Optionpk<string> description_opt(
"d",
"description",
"Set image description");
156 extent_opt.setHide(1);
159 msknodata_opt.setHide(1);
160 mskband_opt.setHide(1);
161 option_opt.setHide(1);
163 weight_opt.setHide(1);
164 class_opt.setHide(1);
165 colorTable_opt.setHide(1);
166 description_opt.setHide(1);
170 doProcess=input_opt.retrieveOption(argc,argv);
171 output_opt.retrieveOption(argc,argv);
172 band_opt.retrieveOption(argc,argv);
173 dx_opt.retrieveOption(argc,argv);
174 dy_opt.retrieveOption(argc,argv);
175 extent_opt.retrieveOption(argc,argv);
176 cut_opt.retrieveOption(argc,argv);
177 mask_opt.retrieveOption(argc,argv);
178 msknodata_opt.retrieveOption(argc,argv);
179 mskband_opt.retrieveOption(argc,argv);
180 ulx_opt.retrieveOption(argc,argv);
181 uly_opt.retrieveOption(argc,argv);
182 lrx_opt.retrieveOption(argc,argv);
183 lry_opt.retrieveOption(argc,argv);
184 crule_opt.retrieveOption(argc,argv);
185 ruleBand_opt.retrieveOption(argc,argv);
186 srcnodata_opt.retrieveOption(argc,argv);
187 bndnodata_opt.retrieveOption(argc,argv);
188 minValue_opt.retrieveOption(argc,argv);
189 maxValue_opt.retrieveOption(argc,argv);
190 dstnodata_opt.retrieveOption(argc,argv);
191 resample_opt.retrieveOption(argc,argv);
192 otype_opt.retrieveOption(argc,argv);
193 oformat_opt.retrieveOption(argc,argv);
194 option_opt.retrieveOption(argc,argv);
195 projection_opt.retrieveOption(argc,argv);
196 file_opt.retrieveOption(argc,argv);
197 weight_opt.retrieveOption(argc,argv);
198 class_opt.retrieveOption(argc,argv);
199 colorTable_opt.retrieveOption(argc,argv);
200 description_opt.retrieveOption(argc,argv);
201 verbose_opt.retrieveOption(argc,argv);
203 catch(
string predefinedString){
204 std::cout << predefinedString << std::endl;
209 cout <<
"Usage: pkcomposite -i input [-i input]* -o output" << endl;
211 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
215 std::map<std::string, crule::CRULE_TYPE> cruleMap;
219 cruleMap[
"overwrite"]=crule::overwrite;
220 cruleMap[
"maxndvi"]=crule::maxndvi;
221 cruleMap[
"maxband"]=crule::maxband;
222 cruleMap[
"minband"]=crule::minband;
223 cruleMap[
"validband"]=crule::validband;
224 cruleMap[
"mean"]=crule::mean;
225 cruleMap[
"mode"]=crule::mode;
226 cruleMap[
"median"]=crule::median;
227 cruleMap[
"sum"]=crule::sum;
228 cruleMap[
"maxallbands"]=crule::maxallbands;
229 cruleMap[
"minallbands"]=crule::minallbands;
230 cruleMap[
"stdev"]=crule::stdev;
232 if(srcnodata_opt.size()){
233 while(srcnodata_opt.size()<bndnodata_opt.size())
234 srcnodata_opt.push_back(srcnodata_opt[0]);
236 while(bndnodata_opt.size()<srcnodata_opt.size())
237 bndnodata_opt.push_back(bndnodata_opt[0]);
238 if(minValue_opt.size()){
239 while(minValue_opt.size()<bndnodata_opt.size())
240 minValue_opt.push_back(minValue_opt[0]);
241 while(bndnodata_opt.size()<minValue_opt.size())
242 bndnodata_opt.push_back(bndnodata_opt[0]);
244 if(maxValue_opt.size()){
245 while(maxValue_opt.size()<bndnodata_opt.size())
246 maxValue_opt.push_back(maxValue_opt[0]);
247 while(bndnodata_opt.size()<maxValue_opt.size())
248 bndnodata_opt.push_back(bndnodata_opt[0]);
250 RESAMPLE theResample;
251 if(resample_opt[0]==
"near"){
254 cout <<
"resampling: nearest neighbor" << endl;
256 else if(resample_opt[0]==
"bilinear"){
257 theResample=BILINEAR;
259 cout <<
"resampling: bilinear interpolation" << endl;
262 std::cout <<
"Error: resampling method " << resample_opt[0] <<
" not supported" << std::endl;
266 if(input_opt.empty()){
267 std::cerr <<
"No input file provided (use option -i). Use --help for help information" << std::endl;
280 double magic_x=1,magic_y=1;
282 GDALDataType theType=GDT_Unknown;
284 cout <<
"possible output data types: ";
285 for(
int iType = 0; iType < GDT_TypeCount; ++iType){
287 cout <<
" " << GDALGetDataTypeName((GDALDataType)iType);
288 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
289 && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
290 otype_opt[0].c_str()))
291 theType=(GDALDataType) iType;
295 if(theType==GDT_Unknown)
296 cout <<
"Unknown output pixel type: " << otype_opt[0] << endl;
298 cout <<
"Output pixel type: " << GDALGetDataTypeName(theType) << endl;
305 if(extent_opt.size()){
310 for(
int iextent=0;iextent<extent_opt.size();++iextent){
311 extentReader.open(extent_opt[iextent]);
312 if(!(extentReader.getExtent(e_ulx,e_uly,e_lrx,e_lry))){
313 cerr <<
"Error: could not get extent from " << extent_opt[0] << endl;
332 extentReader.close();
335 extentReader.open(extent_opt[0]);
339 cout <<
"--ulx=" << ulx_opt[0] <<
" --uly=" << uly_opt[0] <<
" --lrx=" << lrx_opt[0] <<
" --lry=" << lry_opt[0] << endl;
342 string theProjection=
"";
343 GDALColorTable* theColorTable=NULL;
346 for(
int ifile=0;ifile<input_opt.size();++ifile){
348 imgReader.open(input_opt[ifile]);
350 catch(
string errorstring){
351 cerr << errorstring <<
" " << input_opt[ifile] << endl;
353 if(colorTable_opt.empty())
354 if(imgReader.getColorTable())
355 theColorTable=(imgReader.getColorTable()->Clone());
356 if(projection_opt.empty())
357 theProjection=imgReader.getProjection();
358 if(option_opt.findSubstring(
"INTERLEAVE=")==option_opt.end()){
359 string theInterleave=
"INTERLEAVE=";
360 theInterleave+=imgReader.getInterleave();
361 option_opt.push_back(theInterleave);
364 if((ulx_opt[0]||uly_opt[0]||lrx_opt[0]||lry_opt[0])&&(!imgReader.covers(ulx_opt[0],uly_opt[0],lrx_opt[0],lry_opt[0]))){
366 cout << input_opt[ifile] <<
" not within bounding box, skipping..." << endl;
370 double theULX, theULY, theLRX, theLRY;
371 imgReader.getBoundingBox(theULX,theULY,theLRX,theLRY);
373 cerr <<
"Error: " << input_opt[ifile] <<
" is not georeferenced, only referenced images are supported for pkcomposite " << endl;
377 cout <<
"Bounding Box (ULX ULY LRX LRY): " << fixed << setprecision(6) << theULX <<
" " << theULY <<
" " << theLRX <<
" " << theLRY << endl;
380 switch(cruleMap[crule_opt[0]]){
382 case(crule::overwrite):
383 cout <<
"Composite rule: overwrite" << endl;
385 case(crule::maxndvi):
386 cout <<
"Composite rule: max ndvi" << endl;
388 case(crule::maxband):
389 cout <<
"Composite rule: max band" << endl;
391 case(crule::minband):
392 cout <<
"Composite rule: min band" << endl;
394 case(crule::validband):
395 cout <<
"Composite rule: valid band" << endl;
398 cout <<
"Composite rule: mean value" << endl;
401 cout <<
"Composite rule: max voting (only for byte images)" << endl;
404 cout <<
"Composite rule: median" << endl;
407 cout <<
"Composite rule: stdev" << endl;
410 cout <<
"Composite rule: sum" << endl;
412 case(crule::minallbands):
413 cout <<
"Composite rule: minallbands" << endl;
415 case(crule::maxallbands):
416 cout <<
"Composite rule: maxallbands" << endl;
421 nband=band_opt.size();
422 bands.resize(band_opt.size());
423 for(
int iband=0;iband<band_opt.size();++iband){
424 bands[iband]=band_opt[iband];
425 assert(bands[iband]<imgReader.nrOfBand());
429 nband=imgReader.nrOfBand();
431 for(
int iband=0;iband<nband;++iband)
434 for(
int iband=0;iband<bndnodata_opt.size();++iband){
435 assert(bndnodata_opt[iband]>=0&&bndnodata_opt[iband]<nband);
438 if(theType==GDT_Unknown){
439 theType=imgReader.getDataType();
441 cout <<
"Using data type from input image: " << GDALGetDataTypeName(theType) << endl;
444 if(oformat_opt.size())
445 imageType=oformat_opt[0];
447 imageType=imgReader.getImageType();
451 cout <<
"type of data for " << input_opt[ifile] <<
": " << theType << endl;
452 cout <<
"nband: " << nband << endl;
462 dx=imgReader.getDeltaX();
466 dy=imgReader.getDeltaY();
480 maxLRX=(theLRX>maxLRX)?theLRX:maxLRX;
481 maxULY=(theULY>maxULY)?theULY:maxULY;
482 minULX=(theULX<minULX)?theULX:minULX;
483 minLRY=(theLRY<minLRY)?theLRY:minLRY;
488 cout <<
"bounding box input images (ULX ULY LRX LRY): " << fixed << setprecision(6) << minULX <<
" " << maxULY <<
" " << maxLRX <<
" " << minLRY << endl;
489 if(ulx_opt[0]||uly_opt[0]||lrx_opt[0]||lry_opt[0]){
496 bool forceEUgrid=
false;
497 if(projection_opt.size())
498 forceEUgrid=(!(projection_opt[0].compare(
"EPSG:3035"))||!(projection_opt[0].compare(
"EPSG:3035"))||projection_opt[0].find(
"ETRS-LAEA")!=string::npos);
501 minULX=floor(minULX);
502 minULX-=
static_cast<int>(minULX)%(static_cast<int>(dx));
504 if(static_cast<int>(maxULY)%static_cast<int>(dy))
506 maxULY-=
static_cast<int>(maxULY)%(static_cast<int>(dy));
508 if(static_cast<int>(maxLRX)%static_cast<int>(dx))
510 maxLRX-=
static_cast<int>(maxLRX)%(static_cast<int>(dx));
511 minLRY=floor(minLRY);
512 minLRY-=
static_cast<int>(minLRY)%(static_cast<int>(dy));
516 cout <<
"bounding box composite image (ULX ULY LRX LRY): " << fixed << setprecision(6) << minULX <<
" " << maxULY <<
" " << maxLRX <<
" " << minLRY << endl;
519 cout <<
"initializing composite image..." << endl;
525 int ncol=ceil((maxLRX-minULX)/dx);
526 int nrow=ceil((maxULY-minLRY)/dy);
529 cout <<
"composite image dim (nrow x ncol): " << nrow <<
" x " << ncol << endl;
531 while(weight_opt.size()<input_opt.size())
532 weight_opt.push_back(weight_opt[0]);
534 std::cout << weight_opt << std::endl;
536 if(cruleMap[crule_opt[0]]==crule::mode){
537 nwriteBand=(file_opt[0])? class_opt.size()+1:class_opt.size();
540 nwriteBand=(file_opt[0])? bands.size()+1:bands.size();
541 if(output_opt.empty()){
542 std::cerr <<
"No output file provided (use option -o). Use --help for help information" << std::endl;
546 cout <<
"open output image " << output_opt[0] <<
" with " << nwriteBand <<
" bands" << endl << flush;
548 imgWriter.open(output_opt[0],ncol,nrow,nwriteBand,theType,imageType,option_opt);
549 for(
int iband=0;iband<nwriteBand;++iband)
550 imgWriter.GDALSetNoDataValue(dstnodata_opt[0],iband);
553 cout << error << endl;
555 if(description_opt.size())
556 imgWriter.setImageDescription(description_opt[0]);
564 imgWriter.setGeoTransform(gt);
566 if(projection_opt.size()){
568 cout <<
"projection: " << projection_opt[0] << endl;
569 imgWriter.setProjectionProj4(projection_opt[0]);
571 else if(theProjection!=
""){
573 cout <<
"projection: " << theProjection << endl;
574 imgWriter.setProjection(theProjection);
576 if(imgWriter.getDataType()==GDT_Byte){
577 if(colorTable_opt.size()){
578 if(colorTable_opt[0]!=
"none")
579 imgWriter.setColorTable(colorTable_opt[0]);
581 else if(theColorTable)
582 imgWriter.setColorTable(theColorTable);
586 if(extent_opt.size()&&cut_opt[0]){
588 maskWriter.open(
"/vsimem/mask.tif",ncol,nrow,1,GDT_Float32,
"GTiff",option_opt);
596 maskWriter.setGeoTransform(gt);
597 if(projection_opt.size())
598 maskWriter.setProjectionProj4(projection_opt[0]);
599 else if(theProjection!=
""){
601 cout <<
"projection: " << theProjection << endl;
602 maskWriter.setProjection(theProjection);
606 vector<double> burnValues(1,1);
607 maskWriter.rasterizeOgr(extentReader,burnValues);
611 cerr << error << std::endl;
615 cerr <<
"error catched" << std::endl;
620 mask_opt.push_back(
"/vsimem/mask.tif");
625 if(verbose_opt[0]>=1)
626 std::cout <<
"opening mask image file " << mask_opt[0] << std::endl;
627 maskReader.open(mask_opt[0]);
628 if(mskband_opt[0]>=maskReader.nrOfBand()){
629 string errorString=
"Error: illegal mask band";
634 cerr << error << std::endl;
638 cerr <<
"error catched" << std::endl;
645 cout <<
"creating composite image" << endl;
647 vector<short> fileBuffer(ncol);
651 if(cruleMap[crule_opt[0]]==crule::maxndvi)
652 assert(ruleBand_opt.size()==2);
653 if(cruleMap[crule_opt[0]]==crule::mode){
654 maxBuffer.resize(imgWriter.nrOfCol(),256);
655 for(
int iclass=0;iclass<class_opt.size();++iclass)
656 assert(class_opt[iclass]<maxBuffer.size());
663 const char* pszMessage;
664 void* pProgressArg=NULL;
665 GDALProgressFunc pfnProgress=GDALTermProgress;
667 pfnProgress(progress,pszMessage,pProgressArg);
668 for(
int irow=0;irow<imgWriter.nrOfRow();++irow){
669 vector<float> lineMask;
671 vector<bool> writeValid(ncol);
676 imgWriter.image2geo(0,irow,x,y);
679 if(cruleMap[crule_opt[0]]==crule::mean ||
680 cruleMap[crule_opt[0]]==crule::median ||
681 cruleMap[crule_opt[0]]==crule::sum ||
682 cruleMap[crule_opt[0]]==crule::minallbands ||
683 cruleMap[crule_opt[0]]==crule::maxallbands ||
684 cruleMap[crule_opt[0]]==crule::stdev)
685 storeBuffer.resize(nband,ncol);
686 for(
int icol=0;icol<imgWriter.nrOfCol();++icol){
687 writeValid[icol]=
false;
689 if(cruleMap[crule_opt[0]]==crule::mode){
690 for(
int iclass=0;iclass<256;++iclass)
691 maxBuffer[icol][iclass]=0;
694 for(
int iband=0;iband<nband;++iband)
695 writeBuffer[iband][icol]=dstnodata_opt[0];
699 double oldRowMask=-1;
701 for(
int ifile=0;ifile<input_opt.size();++ifile){
703 imgReader.open(input_opt[ifile]);
706 cout << error << endl;
709 assert(imgReader.nrOfBand()>=nband);
710 if(!imgReader.covers(minULX,maxULY,maxLRX,minLRY)){
714 double uli,ulj,lri,lrj;
715 imgReader.geo2image(minULX+(magic_x-1.0)*imgReader.getDeltaX(),maxULY-(magic_y-1.0)*imgReader.getDeltaY(),uli,ulj);
716 imgReader.geo2image(maxLRX+(magic_x-2.0)*imgReader.getDeltaX(),minLRY-(magic_y-2.0)*imgReader.getDeltaY(),lri,lrj);
726 else if(uli>=imgReader.nrOfCol())
727 startCol=imgReader.nrOfCol()-1;
730 else if(lri>=imgReader.nrOfCol())
731 endCol=imgReader.nrOfCol()-1;
732 int readncol=endCol-startCol+1;
735 imgReader.geo2image(x,y,readCol,readRow);
736 if(readRow<0||readRow>=imgReader.nrOfRow()){
741 for(
int iband=0;iband<nband;++iband){
742 int readBand=(band_opt.size()>iband)? band_opt[iband] : iband;
743 readBuffer[iband].resize(readncol);
745 imgReader.readData(readBuffer[iband],GDT_Float64,startCol,endCol,readRow,readBand,theResample);
748 cerr <<
"error reading image " << input_opt[ifile] <<
": " << endl;
753 for(
int ib=0;ib<ncol;++ib){
754 imgWriter.image2geo(ib,irow,x,y);
762 maskReader.geo2image(x,y,colMask,rowMask);
763 colMask=
static_cast<int>(colMask);
764 rowMask=
static_cast<int>(rowMask);
765 if(rowMask>=0&&rowMask<maskReader.nrOfRow()&&colMask>=0&&colMask<maskReader.nrOfCol()){
766 if(static_cast<int>(rowMask)!=
static_cast<int>(oldRowMask)){
768 assert(rowMask>=0&&rowMask<maskReader.nrOfRow());
770 maskReader.readData(lineMask,GDT_Float32,static_cast<int>(rowMask),mskband_opt[0]);
772 catch(
string errorstring){
773 cerr << errorstring << endl;
777 cerr <<
"error catched" << std::endl;
782 if(lineMask[colMask]==msknodata_opt[0])
791 imgReader.geo2image(x,y,readCol,readRow);
792 if(readCol<0||readCol>=imgReader.nrOfCol())
794 double val_current=0;
799 lowerCol=readCol-0.5;
800 lowerCol=
static_cast<int>(lowerCol);
801 upperCol=readCol+0.5;
802 upperCol=
static_cast<int>(upperCol);
805 if(upperCol>=imgReader.nrOfCol())
806 upperCol=imgReader.nrOfCol()-1;
807 for(
int vband=0;vband<bndnodata_opt.size();++vband){
808 val_new=(readCol-0.5-lowerCol)*readBuffer[bndnodata_opt[vband]][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[bndnodata_opt[vband]][lowerCol-startCol];
809 if(minValue_opt.size()>vband){
810 if(val_new<=minValue_opt[vband]){
815 if(maxValue_opt.size()>vband){
816 if(val_new>=maxValue_opt[vband]){
821 if(srcnodata_opt.size()>vband){
822 if(val_new==srcnodata_opt[vband]){
830 readCol=
static_cast<int>(readCol);
831 for(
int vband=0;vband<bndnodata_opt.size();++vband){
832 val_new=readBuffer[bndnodata_opt[vband]][readCol-startCol];
833 if(minValue_opt.size()>vband){
834 if(val_new<=minValue_opt[vband]){
839 if(maxValue_opt.size()>vband){
840 if(val_new>=maxValue_opt[vband]){
845 if(srcnodata_opt.size()>vband){
846 if(val_new==srcnodata_opt[vband]){
859 switch(cruleMap[crule_opt[0]]){
860 case(crule::maxndvi):{
861 double red_current=writeBuffer[ruleBand_opt[0]][ib];
862 double nir_current=writeBuffer[ruleBand_opt[1]][ib];
863 double ndvi_current=0;
864 if(red_current+nir_current>0&&red_current>=0&&nir_current>=0)
865 ndvi_current=(nir_current-red_current)/(nir_current+red_current);
871 lowerCol=readCol-0.5;
872 lowerCol=
static_cast<int>(lowerCol);
873 upperCol=readCol+0.5;
874 upperCol=
static_cast<int>(upperCol);
877 if(upperCol>=imgReader.nrOfCol())
878 upperCol=imgReader.nrOfCol()-1;
879 red_new=(readCol-0.5-lowerCol)*readBuffer[ruleBand_opt[0]][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ruleBand_opt[0]][lowerCol-startCol];
880 nir_new=(readCol-0.5-lowerCol)*readBuffer[ruleBand_opt[1]][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ruleBand_opt[1]][lowerCol-startCol];
881 if(red_new+nir_new>0&&red_new>=0&&nir_new>=0)
882 ndvi_new=(nir_new-red_new)/(nir_new+red_new);
883 if(ndvi_new>=ndvi_current){
884 for(iband=0;iband<nband;++iband){
885 val_new=(readCol-0.5-lowerCol)*readBuffer[iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[iband][lowerCol-startCol];
886 writeBuffer[iband][ib]=val_new;
889 fileBuffer[ib]=ifile;
893 readCol=
static_cast<int>(readCol);
894 red_new=readBuffer[ruleBand_opt[0]][readCol-startCol];
895 nir_new=readBuffer[ruleBand_opt[1]][readCol-startCol];
896 if(red_new+nir_new>0&&red_new>=0&&nir_new>=0)
897 ndvi_new=(nir_new-red_new)/(nir_new+red_new);
898 if(ndvi_new>=ndvi_current){
899 for(iband=0;iband<nband;++iband){
900 val_new=readBuffer[iband][readCol-startCol];
901 writeBuffer[iband][ib]=val_new;
904 fileBuffer[ib]=ifile;
910 case(crule::maxband):
911 case(crule::minband):
912 case(crule::validband):
913 val_current=writeBuffer[ruleBand_opt[0]][ib];
916 lowerCol=readCol-0.5;
917 lowerCol=
static_cast<int>(lowerCol);
918 upperCol=readCol+0.5;
919 upperCol=
static_cast<int>(upperCol);
922 if(upperCol>=imgReader.nrOfCol())
923 upperCol=imgReader.nrOfCol()-1;
924 val_new=(readCol-0.5-lowerCol)*readBuffer[ruleBand_opt[0]][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ruleBand_opt[0]][lowerCol-startCol];
925 val_new*=weight_opt[ifile];
926 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)){
927 for(iband=0;iband<nband;++iband){
928 val_new=(readCol-0.5-lowerCol)*readBuffer[iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[iband][lowerCol-startCol];
929 val_new*=weight_opt[ifile];
930 writeBuffer[iband][ib]=val_new;
933 fileBuffer[ib]=ifile;
937 readCol=
static_cast<int>(readCol);
938 val_new=readBuffer[ruleBand_opt[0]][readCol-startCol];
939 val_new*=weight_opt[ifile];
940 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)){
941 for(iband=0;iband<nband;++iband){
942 val_new=readBuffer[iband][readCol-startCol];
943 val_new*=weight_opt[ifile];
944 writeBuffer[iband][ib]=val_new;
947 fileBuffer[ib]=ifile;
955 lowerCol=readCol-0.5;
956 lowerCol=
static_cast<int>(lowerCol);
957 upperCol=readCol+0.5;
958 upperCol=
static_cast<int>(upperCol);
961 if(upperCol>=imgReader.nrOfCol())
962 upperCol=imgReader.nrOfCol()-1;
963 for(iband=0;iband<nband;++iband){
964 val_new=(readCol-0.5-lowerCol)*readBuffer[iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[iband][lowerCol-startCol];
965 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
970 readCol=
static_cast<int>(readCol);
971 for(iband=0;iband<nband;++iband){
972 val_new=readBuffer[iband][readCol-startCol];
973 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
981 case(crule::minallbands):
982 case(crule::maxallbands):
986 lowerCol=readCol-0.5;
987 lowerCol=
static_cast<int>(lowerCol);
988 upperCol=readCol+0.5;
989 upperCol=
static_cast<int>(upperCol);
992 if(upperCol>=imgReader.nrOfCol())
993 upperCol=imgReader.nrOfCol()-1;
994 for(iband=0;iband<nband;++iband){
995 val_new=(readCol-0.5-lowerCol)*readBuffer[iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[iband][lowerCol-startCol];
996 val_new*=weight_opt[ifile];
997 storeBuffer[iband][ib].push_back(val_new);
1001 readCol=
static_cast<int>(readCol);
1002 for(iband=0;iband<nband;++iband){
1003 val_new=readBuffer[iband][readCol-startCol];
1004 val_new*=weight_opt[ifile];
1005 storeBuffer[iband][ib].push_back(val_new);
1013 fileBuffer[ib]=ifile;
1015 case(crule::overwrite):
1017 switch(theResample){
1019 lowerCol=readCol-0.5;
1020 lowerCol=
static_cast<int>(lowerCol);
1021 upperCol=readCol+0.5;
1022 upperCol=
static_cast<int>(upperCol);
1025 if(upperCol>=imgReader.nrOfCol())
1026 upperCol=imgReader.nrOfCol()-1;
1027 for(iband=0;iband<nband;++iband){
1028 val_new=(readCol-0.5-lowerCol)*readBuffer[iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[iband][lowerCol-startCol];
1029 val_new*=weight_opt[ifile];
1030 writeBuffer[iband][ib]=val_new;
1034 readCol=
static_cast<int>(readCol);
1035 for(iband=0;iband<nband;++iband){
1036 val_new=readBuffer[iband][readCol-startCol];
1037 val_new*=weight_opt[ifile];
1038 writeBuffer[iband][ib]=val_new;
1043 fileBuffer[ib]=ifile;
1048 writeValid[ib]=
true;
1050 switch(cruleMap[crule_opt[0]]){
1052 case(crule::median):
1054 case(crule::minallbands):
1055 case(crule::maxallbands):
1057 switch(theResample){
1059 lowerCol=readCol-0.5;
1060 lowerCol=
static_cast<int>(lowerCol);
1061 upperCol=readCol+0.5;
1062 upperCol=
static_cast<int>(upperCol);
1065 if(upperCol>=imgReader.nrOfCol())
1066 upperCol=imgReader.nrOfCol()-1;
1067 for(iband=0;iband<nband;++iband){
1068 val_new=(readCol-0.5-lowerCol)*readBuffer[iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[iband][lowerCol-startCol];
1069 val_new*=weight_opt[ifile];
1070 storeBuffer[iband][ib].push_back(val_new);
1074 readCol=
static_cast<int>(readCol);
1075 for(iband=0;iband<nband;++iband){
1076 val_new=readBuffer[iband][readCol-startCol];
1077 val_new*=weight_opt[ifile];
1078 storeBuffer[iband][ib].push_back(val_new);
1083 fileBuffer[ib]=ifile;
1086 switch(theResample){
1088 lowerCol=readCol-0.5;
1089 lowerCol=
static_cast<int>(lowerCol);
1090 upperCol=readCol+0.5;
1091 upperCol=
static_cast<int>(upperCol);
1094 if(upperCol>=imgReader.nrOfCol())
1095 upperCol=imgReader.nrOfCol()-1;
1096 for(iband=0;iband<nband;++iband){
1097 val_new=(readCol-0.5-lowerCol)*readBuffer[iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[iband][lowerCol-startCol];
1098 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1103 readCol=
static_cast<int>(readCol);
1104 for(iband=0;iband<nband;++iband){
1105 val_new=readBuffer[iband][readCol-startCol];
1106 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1113 switch(theResample){
1115 lowerCol=readCol-0.5;
1116 lowerCol=
static_cast<int>(lowerCol);
1117 upperCol=readCol+0.5;
1118 upperCol=
static_cast<int>(upperCol);
1121 if(upperCol>=imgReader.nrOfCol())
1122 upperCol=imgReader.nrOfCol()-1;
1123 for(iband=0;iband<nband;++iband){
1124 val_new=(readCol-0.5-lowerCol)*readBuffer[iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[iband][lowerCol-startCol];
1125 val_new*=weight_opt[ifile];
1126 writeBuffer[iband][ib]=val_new;
1130 readCol=
static_cast<int>(readCol);
1131 for(iband=0;iband<nband;++iband){
1132 val_new=readBuffer[iband][readCol-startCol];
1133 val_new*=weight_opt[ifile];
1134 writeBuffer[iband][ib]=val_new;
1139 fileBuffer[ib]=ifile;
1147 if(cruleMap[crule_opt[0]]==crule::mode){
1148 vector<short> classBuffer(imgWriter.nrOfCol());
1149 if(class_opt.size()>1){
1150 for(
int iclass=0;iclass<class_opt.size();++iclass){
1151 for(
int icol=0;icol<imgWriter.nrOfCol();++icol)
1152 classBuffer[icol]=maxBuffer[icol][class_opt[iclass]];
1154 imgWriter.writeData(classBuffer,GDT_Int16,irow,iclass);
1156 catch(
string error){
1157 cerr <<
"error writing image file " << output_opt[0] <<
": " << error << endl;
1163 for(
int icol=0;icol<imgWriter.nrOfCol();++icol){
1164 vector<short>::iterator maxit=maxBuffer[icol].begin();
1165 maxit=stat.mymax(maxBuffer[icol],maxBuffer[icol].begin(),maxBuffer[icol].end());
1166 writeBuffer[0][icol]=distance(maxBuffer[icol].begin(),maxit);
1168 fileBuffer[icol]=*(maxit);
1171 imgWriter.writeData(writeBuffer[0],GDT_Float64,irow,0);
1173 imgWriter.writeData(fileBuffer,GDT_Int16,irow,1);
1175 catch(
string error){
1176 cerr <<
"error writing image file " << output_opt[0] <<
": " << error << endl;
1182 for(
int iband=0;iband<bands.size();++iband){
1184 assert(writeBuffer[iband].size()==imgWriter.nrOfCol());
1185 for(
int icol=0;icol<imgWriter.nrOfCol();++icol){
1187 switch(cruleMap[crule_opt[0]]){
1190 writeBuffer[iband][icol]=stat.mean(storeBuffer[iband][icol]);
1192 case(crule::median):
1194 writeBuffer[iband][icol]=stat.median(storeBuffer[iband][icol]);
1198 writeBuffer[iband][icol]=stat.sum(storeBuffer[iband][icol]);
1200 case(crule::minallbands):
1202 writeBuffer[iband][icol]=stat.mymin(storeBuffer[iband][icol]);
1204 case(crule::maxallbands):
1206 writeBuffer[iband][icol]=stat.mymax(storeBuffer[iband][icol]);
1210 writeBuffer[iband][icol]=sqrt(stat.var(storeBuffer[iband][icol]));
1216 catch(
string error){
1218 cerr << error << endl;
1219 writeBuffer[iband][icol]=dstnodata_opt[0];
1224 imgWriter.writeData(writeBuffer[iband],GDT_Float64,irow,iband);
1226 catch(
string error){
1227 cerr << error <<
" in " << output_opt[0] << endl;
1233 imgWriter.writeData(fileBuffer,GDT_Int16,irow,bands.size());
1235 catch(
string error){
1236 cerr << error <<
" in " << output_opt[0] << endl;
1241 progress=
static_cast<float>(irow+1.0)/imgWriter.nrOfRow();
1242 pfnProgress(progress,pszMessage,pProgressArg);
1244 if(extent_opt.size()&&cut_opt.size()){
1245 extentReader.close();