pktools  2.6.3
Processing Kernel for geospatial data
pkgetmask.cc
1 /**********************************************************************
2 pkgetmask.cc: program to create mask image based on values in input raster image
3 Copyright (C) 2008-2014 Pieter Kempeneers
4 
5 This file is part of pktools
6 
7 pktools is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 pktools is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with pktools. If not, see <http://www.gnu.org/licenses/>.
19 ***********************************************************************/
20 #include <assert.h>
21 #include <vector>
22 #include "imageclasses/ImgReaderGdal.h"
23 #include "imageclasses/ImgWriterGdal.h"
24 #include "base/Optionpk.h"
25 
26 using namespace std;
27 int main(int argc,char **argv) {
28  Optionpk<string> input_opt("i", "input", "Input image file");
29  Optionpk<short> band_opt("b", "band", "band(s) used for mask", 0);
30  Optionpk<double> min_opt("min", "min", "Values smaller than min threshold(s) are masked as invalid. Use one threshold for each band");
31  Optionpk<double> max_opt("max", "max", "Values greater than max threshold(s) are masked as invalid. Use one threshold for each band");
32  Optionpk<string> operator_opt("p", "operator", "Operator: [AND,OR].", "OR");
33  Optionpk<unsigned short> data_opt("data", "data", "value(s) for valid pixels: between min and max", 1);
34  Optionpk<unsigned short> nodata_opt("nodata", "nodata", "value(s) for invalid pixels: not between min and max", 0);
35  Optionpk<string> output_opt("o", "output", "Output mask file");
36  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", "Byte");
37  Optionpk<string> oformat_opt("of", "oformat", "Output image format (see also gdal_translate). Empty string: inherit from input image");
38  Optionpk<string> option_opt("co", "co", "Creation option for output file. Multiple options can be specified.");
39  Optionpk<string> colorTable_opt("ct", "ct", "color table (file with 5 columns: id R G B ALFA (0: transparent, 255: solid)");
40  Optionpk<short> verbose_opt("v", "verbose", "verbose", 0,2);
41 
42  band_opt.setHide(1);
43  operator_opt.setHide(1);
44  otype_opt.setHide(1);
45  oformat_opt.setHide(1);
46  option_opt.setHide(1);
47  colorTable_opt.setHide(1);
48 
49  bool doProcess;//stop process when program was invoked with help option (-h --help)
50  try{
51  doProcess=input_opt.retrieveOption(argc,argv);
52  output_opt.retrieveOption(argc,argv);
53  min_opt.retrieveOption(argc,argv);
54  max_opt.retrieveOption(argc,argv);
55  data_opt.retrieveOption(argc,argv);
56  nodata_opt.retrieveOption(argc,argv);
57  band_opt.retrieveOption(argc,argv);
58  operator_opt.retrieveOption(argc,argv);
59  otype_opt.retrieveOption(argc,argv);
60  oformat_opt.retrieveOption(argc,argv);
61  option_opt.retrieveOption(argc,argv);
62  colorTable_opt.retrieveOption(argc,argv);
63  verbose_opt.retrieveOption(argc,argv);
64  }
65  catch(string predefinedString){
66  std::cout << predefinedString << std::endl;
67  exit(0);
68  }
69  if(!doProcess){
70  cout << endl;
71  cout << "Usage: pkgetmask -i input -o output" << endl;
72  cout << endl;
73  std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
74  exit(0);//help was invoked, stop processing
75  }
76 
77  const char* pszMessage;
78  void* pProgressArg=NULL;
79  GDALProgressFunc pfnProgress=GDALTermProgress;
80  double progress=0;
81  pfnProgress(progress,pszMessage,pProgressArg);
82  GDALDataType theType=GDT_Unknown;
83  if(verbose_opt[0])
84  cout << "possible output data types: ";
85  for(int iType = 0; iType < GDT_TypeCount; ++iType){
86  if(verbose_opt[0])
87  cout << " " << GDALGetDataTypeName((GDALDataType)iType);
88  if( GDALGetDataTypeName((GDALDataType)iType) != NULL
89  && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
90  otype_opt[0].c_str()))
91  theType=(GDALDataType) iType;
92  }
93  if(verbose_opt[0]){
94  cout << endl;
95  if(theType==GDT_Unknown)
96  cout << "Unknown output pixel type: " << otype_opt[0] << endl;
97  else
98  cout << "Output pixel type: " << GDALGetDataTypeName(theType) << endl;
99  }
100 
101  assert(input_opt.size());
102  ImgReaderGdal imgReader(input_opt[0]);
103  assert(band_opt.size()>=0);
104  assert(band_opt.size()<=imgReader.nrOfBand());
105 
106  if(min_opt.size()&&max_opt.size()){
107  if(min_opt.size()!=max_opt.size())
108  cerr << "Error: number of min and max options must correspond if both min and max options are provide" << endl;
109  assert(min_opt.size()==max_opt.size());
110  }
111  if(min_opt.size()){
112  while(band_opt.size()>min_opt.size())
113  min_opt.push_back(min_opt[0]);
114  while(min_opt.size()>data_opt.size())
115  data_opt.push_back(data_opt[0]);
116  }
117  if(max_opt.size()){
118  while(band_opt.size()>max_opt.size())
119  max_opt.push_back(max_opt[0]);
120  while(max_opt.size()>data_opt.size())
121  data_opt.push_back(data_opt[0]);
122  }
123  // assert(min_opt.size()==max_opt.size());
124  // if(verbose_opt[0]){
125  // cout << "min,max values: ";
126  // for(int imin=0;imin<min_opt.size();++imin){
127  // cout << min_opt[imin] << "," << max_opt[imin];
128  // if(imin<min_opt.size()-1)
129  // cout << " ";
130  // else
131  // cout << endl;
132  // }
133  // }
134 
135  vector< vector<float> > lineBuffer(band_opt.size());
136  for(int iband=0;iband<band_opt.size();++iband)
137  lineBuffer.resize(imgReader.nrOfCol());
138  ImgWriterGdal imgWriter;
139  //if output type not set, get type from input image
140  if(theType==GDT_Unknown){
141  theType=imgReader.getDataType();
142  if(verbose_opt[0])
143  cout << "Using data type from input image: " << GDALGetDataTypeName(theType) << endl;
144  }
145  string imageType=imgReader.getImageType();
146  if(oformat_opt.size())//default
147  imageType=oformat_opt[0];
148  if(option_opt.findSubstring("INTERLEAVE=")==option_opt.end()){
149  string theInterleave="INTERLEAVE=";
150  theInterleave+=imgReader.getInterleave();
151  option_opt.push_back(theInterleave);
152  }
153  assert(output_opt.size());
154  imgWriter.open(output_opt[0],imgReader.nrOfCol(),imgReader.nrOfRow(),1,theType,imageType,option_opt);
155  if(colorTable_opt.size()){
156  if(colorTable_opt[0]!="none")
157  imgWriter.setColorTable(colorTable_opt[0]);
158  }
159  else if (imgReader.getColorTable()!=NULL)//copy colorTable from input image
160  imgWriter.setColorTable(imgReader.getColorTable());
161 
162  imgWriter.setProjection(imgReader.getProjection());
163  double gt[6];
164  imgReader.getGeoTransform(gt);
165  imgWriter.setGeoTransform(gt);//ulx,uly,imgReader.getDeltaX(),imgReader.getDeltaY(),0,0);
166 
167  if(nodata_opt.size())
168  imgWriter.GDALSetNoDataValue(nodata_opt[0]);
169 
170  vector<char> writeBuffer(imgWriter.nrOfCol());
171  for(int irow=0;irow<imgReader.nrOfRow();++irow){
172  for(int iband=0;iband<band_opt.size();++iband)
173  imgReader.readData(lineBuffer[iband],GDT_Float32,irow,band_opt[iband]);
174  for(int icol=0;icol<imgReader.nrOfCol();++icol){
175  bool valid=(operator_opt[0]=="OR")?false:true;
176  unsigned short validValue=data_opt[0];
177  if(min_opt.size()&&max_opt.size()){
178  assert(max_opt.size()==min_opt.size());
179  for(int ivalid=0;ivalid<min_opt.size();++ivalid){
180  bool validBand=false;
181  // for(int iband=0;iband<band_opt.size();++iband){
182  unsigned short theBand=(band_opt.size()==min_opt.size())? ivalid:0;
183  if(lineBuffer[theBand][icol]>=min_opt[ivalid]&&lineBuffer[theBand][icol]<=max_opt[ivalid]){
184  validValue=data_opt[ivalid];
185  validBand=true;
186  }
187  valid=(operator_opt[0]=="OR")?valid||validBand : valid&&validBand;
188  }
189  }
190  else if(min_opt.size()){
191  for(int ivalid=0;ivalid<min_opt.size();++ivalid){
192  bool validBand=false;
193  // for(int iband=0;iband<band_opt.size();++iband){
194  unsigned short theBand=(band_opt.size()==min_opt.size())? ivalid:0;
195  if(lineBuffer[theBand][icol]>=min_opt[ivalid]){
196  validValue=data_opt[ivalid];
197  validBand=true;
198  }
199  valid=(operator_opt[0]=="OR")?valid||validBand : valid&&validBand;
200  }
201  }
202  else if(max_opt.size()){
203  for(int ivalid=0;ivalid<max_opt.size();++ivalid){
204  bool validBand=false;
205  // for(int iband=0;iband<band_opt.size();++iband){
206  unsigned short theBand=(band_opt.size()==max_opt.size())? ivalid:0;
207  if(lineBuffer[theBand][icol]<=max_opt[ivalid]){
208  validValue=data_opt[ivalid];
209  validBand=true;
210  }
211  valid=(operator_opt[0]=="OR")?valid||validBand : valid&&validBand;
212  }
213  }
214  if(valid)
215  writeBuffer[icol]=validValue;
216  else
217  writeBuffer[icol]=nodata_opt[0];
218  }
219  imgWriter.writeData(writeBuffer,GDT_Byte,irow);
220  progress=(1.0+irow)/imgWriter.nrOfRow();
221  pfnProgress(progress,pszMessage,pProgressArg);
222  }
223 
224  imgReader.close();
225  imgWriter.close();
226 }