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"
135 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};
140 int main(
int argc,
char *argv[])
142 Optionpk<string> input_opt(
"i",
"input",
"Input image file(s). If input contains multiple images, a multi-band output is created");
144 Optionpk<int> band_opt(
"b",
"band",
"band index(es) to crop (leave empty if all bands must be retained)");
145 Optionpk<double> dx_opt(
"dx",
"dx",
"Output resolution in x (in meter) (empty: keep original resolution)");
146 Optionpk<double> dy_opt(
"dy",
"dy",
"Output resolution in y (in meter) (empty: keep original resolution)");
147 Optionpk<string> extent_opt(
"e",
"extent",
"get boundary from extent from polygons in vector file");
148 Optionpk<bool> cut_opt(
"cut",
"crop_to_cutline",
"Crop the extent of the target dataset to the extent of the cutline.",
false);
149 Optionpk<string> mask_opt(
"m",
"mask",
"Use the first band of the specified file as a validity mask (0 is nodata).");
150 Optionpk<float> msknodata_opt(
"msknodata",
"msknodata",
"Mask value not to consider for composite.", 0);
151 Optionpk<short> mskband_opt(
"mskband",
"mskband",
"Mask band to read (0 indexed). Provide band for each mask.", 0);
152 Optionpk<double> ulx_opt(
"ulx",
"ulx",
"Upper left x value bounding box", 0.0);
153 Optionpk<double> uly_opt(
"uly",
"uly",
"Upper left y value bounding box", 0.0);
154 Optionpk<double> lrx_opt(
"lrx",
"lrx",
"Lower right x value bounding box", 0.0);
155 Optionpk<double> lry_opt(
"lry",
"lry",
"Lower right y value bounding box", 0.0);
156 Optionpk<string> crule_opt(
"cr",
"crule",
"Composite rule (overwrite, maxndvi, maxband, minband, mean, mode (only for byte images), median, sum, maxallbands, minallbands, stdev",
"overwrite");
157 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);
158 Optionpk<double> srcnodata_opt(
"srcnodata",
"srcnodata",
"invalid value(s) for input raster dataset");
159 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);
160 Optionpk<double> minValue_opt(
"min",
"min",
"flag values smaller or equal to this value as invalid.");
161 Optionpk<double> maxValue_opt(
"max",
"max",
"flag values larger or equal to this value as invalid.");
162 Optionpk<double> dstnodata_opt(
"dstnodata",
"dstnodata",
"nodata value to put in output raster dataset if not valid or out of bounds.", 0);
163 Optionpk<string> resample_opt(
"r",
"resampling-method",
"Resampling method (near: nearest neighbor, bilinear: bi-linear interpolation).",
"near");
164 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",
"");
165 Optionpk<string> oformat_opt(
"of",
"oformat",
"Output image format (see also gdal_translate).",
"GTiff");
166 Optionpk<string> option_opt(
"co",
"co",
"Creation option for output file. Multiple options can be specified.");
167 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");
168 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);
169 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);
170 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);
171 Optionpk<string> colorTable_opt(
"ct",
"ct",
"color table file with 5 columns: id R G B ALFA (0: transparent, 255: solid)");
172 Optionpk<string> description_opt(
"d",
"description",
"Set image description");
175 extent_opt.setHide(1);
178 msknodata_opt.setHide(1);
179 mskband_opt.setHide(1);
180 option_opt.setHide(1);
182 weight_opt.setHide(1);
183 class_opt.setHide(1);
184 colorTable_opt.setHide(1);
185 description_opt.setHide(1);
189 doProcess=input_opt.retrieveOption(argc,argv);
190 output_opt.retrieveOption(argc,argv);
191 band_opt.retrieveOption(argc,argv);
192 dx_opt.retrieveOption(argc,argv);
193 dy_opt.retrieveOption(argc,argv);
194 extent_opt.retrieveOption(argc,argv);
195 cut_opt.retrieveOption(argc,argv);
196 mask_opt.retrieveOption(argc,argv);
197 msknodata_opt.retrieveOption(argc,argv);
198 mskband_opt.retrieveOption(argc,argv);
199 ulx_opt.retrieveOption(argc,argv);
200 uly_opt.retrieveOption(argc,argv);
201 lrx_opt.retrieveOption(argc,argv);
202 lry_opt.retrieveOption(argc,argv);
203 crule_opt.retrieveOption(argc,argv);
204 ruleBand_opt.retrieveOption(argc,argv);
205 srcnodata_opt.retrieveOption(argc,argv);
206 bndnodata_opt.retrieveOption(argc,argv);
207 minValue_opt.retrieveOption(argc,argv);
208 maxValue_opt.retrieveOption(argc,argv);
209 dstnodata_opt.retrieveOption(argc,argv);
210 resample_opt.retrieveOption(argc,argv);
211 otype_opt.retrieveOption(argc,argv);
212 oformat_opt.retrieveOption(argc,argv);
213 option_opt.retrieveOption(argc,argv);
214 projection_opt.retrieveOption(argc,argv);
215 file_opt.retrieveOption(argc,argv);
216 weight_opt.retrieveOption(argc,argv);
217 class_opt.retrieveOption(argc,argv);
218 colorTable_opt.retrieveOption(argc,argv);
219 description_opt.retrieveOption(argc,argv);
220 verbose_opt.retrieveOption(argc,argv);
222 catch(
string predefinedString){
223 std::cout << predefinedString << std::endl;
228 cout <<
"Usage: pkcomposite -i input [-i input]* -o output" << endl;
230 std::cout <<
"short option -h shows basic options only, use long option --help to show all options" << std::endl;
234 std::map<std::string, crule::CRULE_TYPE> cruleMap;
238 cruleMap[
"overwrite"]=crule::overwrite;
239 cruleMap[
"maxndvi"]=crule::maxndvi;
240 cruleMap[
"maxband"]=crule::maxband;
241 cruleMap[
"minband"]=crule::minband;
242 cruleMap[
"validband"]=crule::validband;
243 cruleMap[
"mean"]=crule::mean;
244 cruleMap[
"mode"]=crule::mode;
245 cruleMap[
"median"]=crule::median;
246 cruleMap[
"sum"]=crule::sum;
247 cruleMap[
"maxallbands"]=crule::maxallbands;
248 cruleMap[
"minallbands"]=crule::minallbands;
249 cruleMap[
"stdev"]=crule::stdev;
251 if(srcnodata_opt.size()){
252 while(srcnodata_opt.size()<bndnodata_opt.size())
253 srcnodata_opt.push_back(srcnodata_opt[0]);
255 while(bndnodata_opt.size()<srcnodata_opt.size())
256 bndnodata_opt.push_back(bndnodata_opt[0]);
257 if(minValue_opt.size()){
258 while(minValue_opt.size()<bndnodata_opt.size())
259 minValue_opt.push_back(minValue_opt[0]);
260 while(bndnodata_opt.size()<minValue_opt.size())
261 bndnodata_opt.push_back(bndnodata_opt[0]);
263 if(maxValue_opt.size()){
264 while(maxValue_opt.size()<bndnodata_opt.size())
265 maxValue_opt.push_back(maxValue_opt[0]);
266 while(bndnodata_opt.size()<maxValue_opt.size())
267 bndnodata_opt.push_back(bndnodata_opt[0]);
269 RESAMPLE theResample;
270 if(resample_opt[0]==
"near"){
273 cout <<
"resampling: nearest neighbor" << endl;
275 else if(resample_opt[0]==
"bilinear"){
276 theResample=BILINEAR;
278 cout <<
"resampling: bilinear interpolation" << endl;
281 std::cout <<
"Error: resampling method " << resample_opt[0] <<
" not supported" << std::endl;
285 if(input_opt.empty()){
286 std::cerr <<
"No input file provided (use option -i). Use --help for help information" << std::endl;
299 double magic_x=1,magic_y=1;
301 GDALDataType theType=GDT_Unknown;
303 cout <<
"possible output data types: ";
304 for(
int iType = 0; iType < GDT_TypeCount; ++iType){
306 cout <<
" " << GDALGetDataTypeName((GDALDataType)iType);
307 if( GDALGetDataTypeName((GDALDataType)iType) != NULL
308 && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
309 otype_opt[0].c_str()))
310 theType=(GDALDataType) iType;
314 if(theType==GDT_Unknown)
315 cout <<
"Unknown output pixel type: " << otype_opt[0] << endl;
317 cout <<
"Output pixel type: " << GDALGetDataTypeName(theType) << endl;
324 if(extent_opt.size()){
329 for(
int iextent=0;iextent<extent_opt.size();++iextent){
330 extentReader.open(extent_opt[iextent]);
331 if(!(extentReader.getExtent(e_ulx,e_uly,e_lrx,e_lry))){
332 cerr <<
"Error: could not get extent from " << extent_opt[0] << endl;
351 extentReader.close();
354 extentReader.open(extent_opt[0]);
358 cout <<
"--ulx=" << ulx_opt[0] <<
" --uly=" << uly_opt[0] <<
" --lrx=" << lrx_opt[0] <<
" --lry=" << lry_opt[0] << endl;
360 vector<ImgReaderGdal> imgReader(input_opt.size());
361 string theProjection=
"";
362 GDALColorTable* theColorTable=NULL;
365 for(
int ifile=0;ifile<input_opt.size();++ifile){
367 imgReader[ifile].open(input_opt[ifile]);
369 catch(
string errorstring){
370 cerr << errorstring <<
" " << input_opt[ifile] << endl;
374 if(colorTable_opt.empty())
375 if(imgReader[ifile].getColorTable())
376 theColorTable=(imgReader[ifile].getColorTable()->Clone());
377 if(projection_opt.empty())
378 theProjection=imgReader[ifile].getProjection();
379 if(option_opt.findSubstring(
"INTERLEAVE=")==option_opt.end()){
380 string theInterleave=
"INTERLEAVE=";
381 theInterleave+=imgReader[ifile].getInterleave();
382 option_opt.push_back(theInterleave);
385 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]))){
387 cout << input_opt[ifile] <<
" not within bounding box, skipping..." << endl;
391 double theULX, theULY, theLRX, theLRY;
392 imgReader[ifile].getBoundingBox(theULX,theULY,theLRX,theLRY);
394 cerr <<
"Error: " << input_opt[ifile] <<
" is not georeferenced, only referenced images are supported for pkcomposite " << endl;
398 cout <<
"Bounding Box (ULX ULY LRX LRY): " << fixed << setprecision(6) << theULX <<
" " << theULY <<
" " << theLRX <<
" " << theLRY << endl;
401 switch(cruleMap[crule_opt[0]]){
403 case(crule::overwrite):
404 cout <<
"Composite rule: overwrite" << endl;
406 case(crule::maxndvi):
407 cout <<
"Composite rule: max ndvi" << endl;
409 case(crule::maxband):
410 cout <<
"Composite rule: max band" << endl;
412 case(crule::minband):
413 cout <<
"Composite rule: min band" << endl;
415 case(crule::validband):
416 cout <<
"Composite rule: valid band" << endl;
419 cout <<
"Composite rule: mean value" << endl;
422 cout <<
"Composite rule: max voting (only for byte images)" << endl;
425 cout <<
"Composite rule: median" << endl;
428 cout <<
"Composite rule: stdev" << endl;
431 cout <<
"Composite rule: sum" << endl;
433 case(crule::minallbands):
434 cout <<
"Composite rule: minallbands" << endl;
436 case(crule::maxallbands):
437 cout <<
"Composite rule: maxallbands" << endl;
442 nband=band_opt.size();
443 bands.resize(band_opt.size());
444 for(
int iband=0;iband<band_opt.size();++iband){
445 bands[iband]=band_opt[iband];
446 assert(bands[iband]<imgReader[ifile].nrOfBand());
450 nband=imgReader[ifile].nrOfBand();
452 for(
int iband=0;iband<nband;++iband)
455 for(
int iband=0;iband<bndnodata_opt.size();++iband){
456 assert(bndnodata_opt[iband]>=0&&bndnodata_opt[iband]<nband);
459 if(theType==GDT_Unknown){
460 theType=imgReader[ifile].getDataType();
462 cout <<
"Using data type from input image: " << GDALGetDataTypeName(theType) << endl;
465 if(oformat_opt.size())
466 imageType=oformat_opt[0];
468 imageType=imgReader[ifile].getImageType();
472 cout <<
"type of data for " << input_opt[ifile] <<
": " << theType << endl;
473 cout <<
"nband: " << nband << endl;
483 dx=imgReader[ifile].getDeltaX();
487 dy=imgReader[ifile].getDeltaY();
501 maxLRX=(theLRX>maxLRX)?theLRX:maxLRX;
502 maxULY=(theULY>maxULY)?theULY:maxULY;
503 minULX=(theULX<minULX)?theULX:minULX;
504 minLRY=(theLRY<minLRY)?theLRY:minLRY;
509 cout <<
"bounding box input images (ULX ULY LRX LRY): " << fixed << setprecision(6) << minULX <<
" " << maxULY <<
" " << maxLRX <<
" " << minLRY << endl;
510 if(ulx_opt[0]||uly_opt[0]||lrx_opt[0]||lry_opt[0]){
517 bool forceEUgrid=
false;
518 if(projection_opt.size())
519 forceEUgrid=(!(projection_opt[0].compare(
"EPSG:3035"))||!(projection_opt[0].compare(
"EPSG:3035"))||projection_opt[0].find(
"ETRS-LAEA")!=string::npos);
522 minULX=floor(minULX);
523 minULX-=
static_cast<int>(minULX)%(static_cast<int>(dx));
525 if(static_cast<int>(maxULY)%static_cast<int>(dy))
527 maxULY-=
static_cast<int>(maxULY)%(static_cast<int>(dy));
529 if(static_cast<int>(maxLRX)%static_cast<int>(dx))
531 maxLRX-=
static_cast<int>(maxLRX)%(static_cast<int>(dx));
532 minLRY=floor(minLRY);
533 minLRY-=
static_cast<int>(minLRY)%(static_cast<int>(dy));
537 cout <<
"bounding box composite image (ULX ULY LRX LRY): " << fixed << setprecision(6) << minULX <<
" " << maxULY <<
" " << maxLRX <<
" " << minLRY << endl;
540 cout <<
"initializing composite image..." << endl;
546 int ncol=ceil((maxLRX-minULX)/dx);
547 int nrow=ceil((maxULY-minLRY)/dy);
550 cout <<
"composite image dim (nrow x ncol): " << nrow <<
" x " << ncol << endl;
552 while(weight_opt.size()<input_opt.size())
553 weight_opt.push_back(weight_opt[0]);
555 std::cout << weight_opt << std::endl;
557 if(cruleMap[crule_opt[0]]==crule::mode){
558 nwriteBand=(file_opt[0])? class_opt.size()+1:class_opt.size();
561 nwriteBand=(file_opt[0])? bands.size()+1:bands.size();
562 if(output_opt.empty()){
563 std::cerr <<
"No output file provided (use option -o). Use --help for help information" << std::endl;
567 cout <<
"open output image " << output_opt[0] <<
" with " << nwriteBand <<
" bands" << endl << flush;
569 imgWriter.open(output_opt[0],ncol,nrow,nwriteBand,theType,imageType,option_opt);
570 for(
int iband=0;iband<nwriteBand;++iband)
571 imgWriter.GDALSetNoDataValue(dstnodata_opt[0],iband);
574 cout << error << endl;
576 if(description_opt.size())
577 imgWriter.setImageDescription(description_opt[0]);
585 imgWriter.setGeoTransform(gt);
587 if(projection_opt.size()){
589 cout <<
"projection: " << projection_opt[0] << endl;
590 imgWriter.setProjectionProj4(projection_opt[0]);
592 else if(theProjection!=
""){
594 cout <<
"projection: " << theProjection << endl;
595 imgWriter.setProjection(theProjection);
597 if(imgWriter.getDataType()==GDT_Byte){
598 if(colorTable_opt.size()){
599 if(colorTable_opt[0]!=
"none")
600 imgWriter.setColorTable(colorTable_opt[0]);
602 else if(theColorTable)
603 imgWriter.setColorTable(theColorTable);
607 if(extent_opt.size()&&cut_opt[0]){
609 maskWriter.open(
"/vsimem/mask.tif",ncol,nrow,1,GDT_Float32,
"GTiff",option_opt);
617 maskWriter.setGeoTransform(gt);
618 if(projection_opt.size())
619 maskWriter.setProjectionProj4(projection_opt[0]);
620 else if(theProjection!=
""){
622 cout <<
"projection: " << theProjection << endl;
623 maskWriter.setProjection(theProjection);
627 vector<double> burnValues(1,1);
628 maskWriter.rasterizeOgr(extentReader,burnValues);
632 cerr << error << std::endl;
636 cerr <<
"error catched" << std::endl;
641 mask_opt.push_back(
"/vsimem/mask.tif");
646 if(verbose_opt[0]>=1)
647 std::cout <<
"opening mask image file " << mask_opt[0] << std::endl;
648 maskReader.open(mask_opt[0]);
649 if(mskband_opt[0]>=maskReader.nrOfBand()){
650 string errorString=
"Error: illegal mask band";
655 cerr << error << std::endl;
659 cerr <<
"error catched" << std::endl;
666 cout <<
"creating composite image" << endl;
668 vector<short> fileBuffer(ncol);
671 vector<Vector2d<double> > readBuffer(input_opt.size());
672 for(
int ifile=0;ifile<input_opt.size();++ifile)
673 readBuffer[ifile].resize(imgReader[ifile].nrOfBand());
675 if(cruleMap[crule_opt[0]]==crule::maxndvi)
676 assert(ruleBand_opt.size()==2);
677 if(cruleMap[crule_opt[0]]==crule::mode){
678 maxBuffer.resize(imgWriter.nrOfCol(),256);
679 for(
int iclass=0;iclass<class_opt.size();++iclass)
680 assert(class_opt[iclass]<maxBuffer.size());
687 const char* pszMessage;
688 void* pProgressArg=NULL;
689 GDALProgressFunc pfnProgress=GDALTermProgress;
691 pfnProgress(progress,pszMessage,pProgressArg);
692 for(
int irow=0;irow<imgWriter.nrOfRow();++irow){
693 vector<float> lineMask;
695 vector<bool> writeValid(ncol);
700 imgWriter.image2geo(0,irow,x,y);
703 if(cruleMap[crule_opt[0]]==crule::mean ||
704 cruleMap[crule_opt[0]]==crule::median ||
705 cruleMap[crule_opt[0]]==crule::sum ||
706 cruleMap[crule_opt[0]]==crule::minallbands ||
707 cruleMap[crule_opt[0]]==crule::maxallbands ||
708 cruleMap[crule_opt[0]]==crule::stdev)
709 storeBuffer.resize(nband,ncol);
710 for(
int icol=0;icol<imgWriter.nrOfCol();++icol){
711 writeValid[icol]=
false;
713 if(cruleMap[crule_opt[0]]==crule::mode){
714 for(
int iclass=0;iclass<256;++iclass)
715 maxBuffer[icol][iclass]=0;
718 for(
int iband=0;iband<nband;++iband)
719 writeBuffer[iband][icol]=dstnodata_opt[0];
723 double oldRowMask=-1;
725 for(
int ifile=0;ifile<input_opt.size();++ifile){
734 assert(imgReader[ifile].nrOfBand()>=nband);
735 if(!imgReader[ifile].covers(minULX,maxULY,maxLRX,minLRY)){
739 double uli,ulj,lri,lrj;
740 imgReader[ifile].geo2image(minULX+(magic_x-1.0)*imgReader[ifile].getDeltaX(),maxULY-(magic_y-1.0)*imgReader[ifile].getDeltaY(),uli,ulj);
741 imgReader[ifile].geo2image(maxLRX+(magic_x-2.0)*imgReader[ifile].getDeltaX(),minLRY-(magic_y-2.0)*imgReader[ifile].getDeltaY(),lri,lrj);
751 else if(uli>=imgReader[ifile].nrOfCol())
752 startCol=imgReader[ifile].nrOfCol()-1;
755 else if(lri>=imgReader[ifile].nrOfCol())
756 endCol=imgReader[ifile].nrOfCol()-1;
757 int readncol=endCol-startCol+1;
760 imgReader[ifile].geo2image(x,y,readCol,readRow);
761 if(readRow<0||readRow>=imgReader[ifile].nrOfRow()){
766 for(
int iband=0;iband<nband;++iband){
767 int readBand=(band_opt.size()>iband)? band_opt[iband] : iband;
770 imgReader[ifile].readData(readBuffer[ifile][iband],GDT_Float64,startCol,endCol,readRow,readBand,theResample);
773 cerr <<
"error reading image " << input_opt[ifile] <<
": " << endl;
778 for(
int ib=0;ib<ncol;++ib){
779 imgWriter.image2geo(ib,irow,x,y);
787 maskReader.geo2image(x,y,colMask,rowMask);
788 colMask=
static_cast<int>(colMask);
789 rowMask=
static_cast<int>(rowMask);
790 if(rowMask>=0&&rowMask<maskReader.nrOfRow()&&colMask>=0&&colMask<maskReader.nrOfCol()){
791 if(static_cast<int>(rowMask)!=
static_cast<int>(oldRowMask)){
793 assert(rowMask>=0&&rowMask<maskReader.nrOfRow());
795 maskReader.readData(lineMask,GDT_Float32,static_cast<int>(rowMask),mskband_opt[0]);
797 catch(
string errorstring){
798 cerr << errorstring << endl;
802 cerr <<
"error catched" << std::endl;
807 if(lineMask[colMask]==msknodata_opt[0])
816 imgReader[ifile].geo2image(x,y,readCol,readRow);
817 if(readCol<0||readCol>=imgReader[ifile].nrOfCol())
819 double val_current=0;
824 lowerCol=readCol-0.5;
825 lowerCol=
static_cast<int>(lowerCol);
826 upperCol=readCol+0.5;
827 upperCol=
static_cast<int>(upperCol);
830 if(upperCol>=imgReader[ifile].nrOfCol())
831 upperCol=imgReader[ifile].nrOfCol()-1;
832 for(
int vband=0;vband<bndnodata_opt.size();++vband){
833 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];
834 if(minValue_opt.size()>vband){
835 if(val_new<=minValue_opt[vband]){
840 if(maxValue_opt.size()>vband){
841 if(val_new>=maxValue_opt[vband]){
846 if(srcnodata_opt.size()>vband){
847 if(val_new==srcnodata_opt[vband]){
855 readCol=
static_cast<int>(readCol);
856 for(
int vband=0;vband<bndnodata_opt.size();++vband){
857 val_new=readBuffer[ifile][bndnodata_opt[vband]][readCol-startCol];
858 if(minValue_opt.size()>vband){
859 if(val_new<=minValue_opt[vband]){
864 if(maxValue_opt.size()>vband){
865 if(val_new>=maxValue_opt[vband]){
870 if(srcnodata_opt.size()>vband){
871 if(val_new==srcnodata_opt[vband]){
884 switch(cruleMap[crule_opt[0]]){
885 case(crule::maxndvi):{
886 double red_current=writeBuffer[ruleBand_opt[0]][ib];
887 double nir_current=writeBuffer[ruleBand_opt[1]][ib];
888 double ndvi_current=0;
889 if(red_current+nir_current>0&&red_current>=0&&nir_current>=0)
890 ndvi_current=(nir_current-red_current)/(nir_current+red_current);
896 lowerCol=readCol-0.5;
897 lowerCol=
static_cast<int>(lowerCol);
898 upperCol=readCol+0.5;
899 upperCol=
static_cast<int>(upperCol);
902 if(upperCol>=imgReader[ifile].nrOfCol())
903 upperCol=imgReader[ifile].nrOfCol()-1;
904 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];
905 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];
906 if(red_new+nir_new>0&&red_new>=0&&nir_new>=0)
907 ndvi_new=(nir_new-red_new)/(nir_new+red_new);
908 if(ndvi_new>=ndvi_current){
909 for(iband=0;iband<nband;++iband){
910 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
911 writeBuffer[iband][ib]=val_new;
914 fileBuffer[ib]=ifile;
918 readCol=
static_cast<int>(readCol);
919 red_new=readBuffer[ifile][ruleBand_opt[0]][readCol-startCol];
920 nir_new=readBuffer[ifile][ruleBand_opt[1]][readCol-startCol];
921 if(red_new+nir_new>0&&red_new>=0&&nir_new>=0)
922 ndvi_new=(nir_new-red_new)/(nir_new+red_new);
923 if(ndvi_new>=ndvi_current){
924 for(iband=0;iband<nband;++iband){
925 val_new=readBuffer[ifile][iband][readCol-startCol];
926 writeBuffer[iband][ib]=val_new;
929 fileBuffer[ib]=ifile;
935 case(crule::maxband):
936 case(crule::minband):
937 case(crule::validband):
938 val_current=writeBuffer[ruleBand_opt[0]][ib];
941 lowerCol=readCol-0.5;
942 lowerCol=
static_cast<int>(lowerCol);
943 upperCol=readCol+0.5;
944 upperCol=
static_cast<int>(upperCol);
947 if(upperCol>=imgReader[ifile].nrOfCol())
948 upperCol=imgReader[ifile].nrOfCol()-1;
949 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];
950 val_new*=weight_opt[ifile];
951 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)){
952 for(iband=0;iband<nband;++iband){
953 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
954 val_new*=weight_opt[ifile];
955 writeBuffer[iband][ib]=val_new;
958 fileBuffer[ib]=ifile;
962 readCol=
static_cast<int>(readCol);
963 val_new=readBuffer[ifile][ruleBand_opt[0]][readCol-startCol];
964 val_new*=weight_opt[ifile];
965 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)){
966 for(iband=0;iband<nband;++iband){
967 val_new=readBuffer[ifile][iband][readCol-startCol];
968 val_new*=weight_opt[ifile];
969 writeBuffer[iband][ib]=val_new;
972 fileBuffer[ib]=ifile;
980 lowerCol=readCol-0.5;
981 lowerCol=
static_cast<int>(lowerCol);
982 upperCol=readCol+0.5;
983 upperCol=
static_cast<int>(upperCol);
986 if(upperCol>=imgReader[ifile].nrOfCol())
987 upperCol=imgReader[ifile].nrOfCol()-1;
988 for(iband=0;iband<nband;++iband){
989 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
990 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
995 readCol=
static_cast<int>(readCol);
996 for(iband=0;iband<nband;++iband){
997 val_new=readBuffer[ifile][iband][readCol-startCol];
998 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1004 case(crule::median):
1006 case(crule::minallbands):
1007 case(crule::maxallbands):
1009 switch(theResample){
1011 lowerCol=readCol-0.5;
1012 lowerCol=
static_cast<int>(lowerCol);
1013 upperCol=readCol+0.5;
1014 upperCol=
static_cast<int>(upperCol);
1017 if(upperCol>=imgReader[ifile].nrOfCol())
1018 upperCol=imgReader[ifile].nrOfCol()-1;
1019 for(iband=0;iband<nband;++iband){
1020 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1021 val_new*=weight_opt[ifile];
1022 storeBuffer[iband][ib].push_back(val_new);
1026 readCol=
static_cast<int>(readCol);
1027 for(iband=0;iband<nband;++iband){
1028 val_new=readBuffer[ifile][iband][readCol-startCol];
1029 val_new*=weight_opt[ifile];
1030 storeBuffer[iband][ib].push_back(val_new);
1038 fileBuffer[ib]=ifile;
1040 case(crule::overwrite):
1042 switch(theResample){
1044 lowerCol=readCol-0.5;
1045 lowerCol=
static_cast<int>(lowerCol);
1046 upperCol=readCol+0.5;
1047 upperCol=
static_cast<int>(upperCol);
1050 if(upperCol>=imgReader[ifile].nrOfCol())
1051 upperCol=imgReader[ifile].nrOfCol()-1;
1052 for(iband=0;iband<nband;++iband){
1053 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1054 val_new*=weight_opt[ifile];
1055 writeBuffer[iband][ib]=val_new;
1059 readCol=
static_cast<int>(readCol);
1060 for(iband=0;iband<nband;++iband){
1061 val_new=readBuffer[ifile][iband][readCol-startCol];
1062 val_new*=weight_opt[ifile];
1063 writeBuffer[iband][ib]=val_new;
1068 fileBuffer[ib]=ifile;
1073 writeValid[ib]=
true;
1075 switch(cruleMap[crule_opt[0]]){
1077 case(crule::median):
1079 case(crule::minallbands):
1080 case(crule::maxallbands):
1082 switch(theResample){
1084 lowerCol=readCol-0.5;
1085 lowerCol=
static_cast<int>(lowerCol);
1086 upperCol=readCol+0.5;
1087 upperCol=
static_cast<int>(upperCol);
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 storeBuffer[iband][ib].push_back(val_new);
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 storeBuffer[iband][ib].push_back(val_new);
1108 fileBuffer[ib]=ifile;
1111 switch(theResample){
1113 lowerCol=readCol-0.5;
1114 lowerCol=
static_cast<int>(lowerCol);
1115 upperCol=readCol+0.5;
1116 upperCol=
static_cast<int>(upperCol);
1119 if(upperCol>=imgReader[ifile].nrOfCol())
1120 upperCol=imgReader[ifile].nrOfCol()-1;
1121 for(iband=0;iband<nband;++iband){
1122 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1123 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1128 readCol=
static_cast<int>(readCol);
1129 for(iband=0;iband<nband;++iband){
1130 val_new=readBuffer[ifile][iband][readCol-startCol];
1131 maxBuffer[ib][val_new]=maxBuffer[ib][val_new]+weight_opt[ifile];
1138 switch(theResample){
1140 lowerCol=readCol-0.5;
1141 lowerCol=
static_cast<int>(lowerCol);
1142 upperCol=readCol+0.5;
1143 upperCol=
static_cast<int>(upperCol);
1146 if(upperCol>=imgReader[ifile].nrOfCol())
1147 upperCol=imgReader[ifile].nrOfCol()-1;
1148 for(iband=0;iband<nband;++iband){
1149 val_new=(readCol-0.5-lowerCol)*readBuffer[ifile][iband][upperCol-startCol]+(1-readCol+0.5+lowerCol)*readBuffer[ifile][iband][lowerCol-startCol];
1150 val_new*=weight_opt[ifile];
1151 writeBuffer[iband][ib]=val_new;
1155 readCol=
static_cast<int>(readCol);
1156 for(iband=0;iband<nband;++iband){
1157 val_new=readBuffer[ifile][iband][readCol-startCol];
1158 val_new*=weight_opt[ifile];
1159 writeBuffer[iband][ib]=val_new;
1164 fileBuffer[ib]=ifile;
1172 if(cruleMap[crule_opt[0]]==crule::mode){
1173 vector<short> classBuffer(imgWriter.nrOfCol());
1174 if(class_opt.size()>1){
1175 for(
int iclass=0;iclass<class_opt.size();++iclass){
1176 for(
int icol=0;icol<imgWriter.nrOfCol();++icol)
1177 classBuffer[icol]=maxBuffer[icol][class_opt[iclass]];
1179 imgWriter.writeData(classBuffer,GDT_Int16,irow,iclass);
1181 catch(
string error){
1182 cerr <<
"error writing image file " << output_opt[0] <<
": " << error << endl;
1188 for(
int icol=0;icol<imgWriter.nrOfCol();++icol){
1189 vector<short>::iterator maxit=maxBuffer[icol].begin();
1190 maxit=stat.mymax(maxBuffer[icol],maxBuffer[icol].begin(),maxBuffer[icol].end());
1191 writeBuffer[0][icol]=distance(maxBuffer[icol].begin(),maxit);
1193 fileBuffer[icol]=*(maxit);
1196 imgWriter.writeData(writeBuffer[0],GDT_Float64,irow,0);
1198 imgWriter.writeData(fileBuffer,GDT_Int16,irow,1);
1200 catch(
string error){
1201 cerr <<
"error writing image file " << output_opt[0] <<
": " << error << endl;
1207 for(
int iband=0;iband<bands.size();++iband){
1209 assert(writeBuffer[iband].size()==imgWriter.nrOfCol());
1210 for(
int icol=0;icol<imgWriter.nrOfCol();++icol){
1212 switch(cruleMap[crule_opt[0]]){
1215 writeBuffer[iband][icol]=stat.mean(storeBuffer[iband][icol]);
1217 case(crule::median):
1219 writeBuffer[iband][icol]=stat.median(storeBuffer[iband][icol]);
1223 writeBuffer[iband][icol]=stat.sum(storeBuffer[iband][icol]);
1225 case(crule::minallbands):
1227 writeBuffer[iband][icol]=stat.mymin(storeBuffer[iband][icol]);
1229 case(crule::maxallbands):
1231 writeBuffer[iband][icol]=stat.mymax(storeBuffer[iband][icol]);
1235 writeBuffer[iband][icol]=sqrt(stat.var(storeBuffer[iband][icol]));
1241 catch(
string error){
1243 cerr << error << endl;
1244 writeBuffer[iband][icol]=dstnodata_opt[0];
1249 imgWriter.writeData(writeBuffer[iband],GDT_Float64,irow,iband);
1251 catch(
string error){
1252 cerr << error <<
" in " << output_opt[0] << endl;
1258 imgWriter.writeData(fileBuffer,GDT_Int16,irow,bands.size());
1260 catch(
string error){
1261 cerr << error <<
" in " << output_opt[0] << endl;
1266 progress=
static_cast<float>(irow+1.0)/imgWriter.nrOfRow();
1267 pfnProgress(progress,pszMessage,pProgressArg);
1269 if(extent_opt.size()&&cut_opt.size()){
1270 extentReader.close();
1272 for(
int ifile=0;ifile<input_opt.size();++ifile)
1273 imgReader[ifile].close();