pktools  2.6.7
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 /******************************************************************************/
71 using namespace std;
72 int main(int argc,char **argv) {
73  Optionpk<string> input_opt("i", "input", "Input image file");
74  Optionpk<short> band_opt("b", "band", "band(s) used for mask", 0);
75  Optionpk<double> min_opt("min", "min", "Values smaller than min threshold(s) are masked as invalid. Use one threshold for each band");
76  Optionpk<double> max_opt("max", "max", "Values greater than max threshold(s) are masked as invalid. Use one threshold for each band");
77  Optionpk<string> operator_opt("p", "operator", "Operator: [AND,OR].", "OR");
78  Optionpk<unsigned short> data_opt("data", "data", "value(s) for valid pixels: between min and max", 1);
79  Optionpk<unsigned short> nodata_opt("nodata", "nodata", "value(s) for invalid pixels: not between min and max", 0);
80  Optionpk<string> output_opt("o", "output", "Output mask file");
81  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");
82  Optionpk<string> oformat_opt("of", "oformat", "Output image format (see also gdal_translate).","GTiff");
83  Optionpk<string> option_opt("co", "co", "Creation option for output file. Multiple options can be specified.");
84  Optionpk<string> colorTable_opt("ct", "ct", "color table (file with 5 columns: id R G B ALFA (0: transparent, 255: solid)");
85  Optionpk<short> verbose_opt("v", "verbose", "verbose", 0,2);
86 
87  band_opt.setHide(1);
88  operator_opt.setHide(1);
89  otype_opt.setHide(1);
90  oformat_opt.setHide(1);
91  option_opt.setHide(1);
92  colorTable_opt.setHide(1);
93 
94  bool doProcess;//stop process when program was invoked with help option (-h --help)
95  try{
96  doProcess=input_opt.retrieveOption(argc,argv);
97  output_opt.retrieveOption(argc,argv);
98  min_opt.retrieveOption(argc,argv);
99  max_opt.retrieveOption(argc,argv);
100  data_opt.retrieveOption(argc,argv);
101  nodata_opt.retrieveOption(argc,argv);
102  band_opt.retrieveOption(argc,argv);
103  operator_opt.retrieveOption(argc,argv);
104  otype_opt.retrieveOption(argc,argv);
105  oformat_opt.retrieveOption(argc,argv);
106  option_opt.retrieveOption(argc,argv);
107  colorTable_opt.retrieveOption(argc,argv);
108  verbose_opt.retrieveOption(argc,argv);
109  }
110  catch(string predefinedString){
111  std::cout << predefinedString << std::endl;
112  exit(0);
113  }
114  if(!doProcess){
115  cout << endl;
116  cout << "Usage: pkgetmask -i input -o output" << endl;
117  cout << endl;
118  std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
119  exit(0);//help was invoked, stop processing
120  }
121 
122  const char* pszMessage;
123  void* pProgressArg=NULL;
124  GDALProgressFunc pfnProgress=GDALTermProgress;
125  double progress=0;
126  pfnProgress(progress,pszMessage,pProgressArg);
127  GDALDataType theType=GDT_Unknown;
128  if(verbose_opt[0])
129  cout << "possible output data types: ";
130  for(int iType = 0; iType < GDT_TypeCount; ++iType){
131  if(verbose_opt[0])
132  cout << " " << GDALGetDataTypeName((GDALDataType)iType);
133  if( GDALGetDataTypeName((GDALDataType)iType) != NULL
134  && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
135  otype_opt[0].c_str()))
136  theType=(GDALDataType) iType;
137  }
138  if(verbose_opt[0]){
139  cout << endl;
140  if(theType==GDT_Unknown)
141  cout << "Unknown output pixel type: " << otype_opt[0] << endl;
142  else
143  cout << "Output pixel type: " << GDALGetDataTypeName(theType) << endl;
144  }
145 
146  assert(input_opt.size());
147  ImgReaderGdal imgReader(input_opt[0]);
148  assert(band_opt.size()>=0);
149  assert(band_opt.size()<=imgReader.nrOfBand());
150 
151  if(min_opt.size()&&max_opt.size()){
152  if(min_opt.size()!=max_opt.size())
153  cerr << "Error: number of min and max options must correspond if both min and max options are provide" << endl;
154  assert(min_opt.size()==max_opt.size());
155  }
156  if(min_opt.size()){
157  while(band_opt.size()>min_opt.size())
158  min_opt.push_back(min_opt[0]);
159  while(min_opt.size()>data_opt.size())
160  data_opt.push_back(data_opt[0]);
161  }
162  if(max_opt.size()){
163  while(band_opt.size()>max_opt.size())
164  max_opt.push_back(max_opt[0]);
165  while(max_opt.size()>data_opt.size())
166  data_opt.push_back(data_opt[0]);
167  }
168  // assert(min_opt.size()==max_opt.size());
169  // if(verbose_opt[0]){
170  // cout << "min,max values: ";
171  // for(int imin=0;imin<min_opt.size();++imin){
172  // cout << min_opt[imin] << "," << max_opt[imin];
173  // if(imin<min_opt.size()-1)
174  // cout << " ";
175  // else
176  // cout << endl;
177  // }
178  // }
179 
180  vector< vector<float> > lineBuffer(band_opt.size());
181  for(int iband=0;iband<band_opt.size();++iband)
182  lineBuffer.resize(imgReader.nrOfCol());
183  ImgWriterGdal imgWriter;
184  //if output type not set, get type from input image
185  if(theType==GDT_Unknown){
186  theType=imgReader.getDataType();
187  if(verbose_opt[0])
188  cout << "Using data type from input image: " << GDALGetDataTypeName(theType) << endl;
189  }
190  string imageType;//=imgReader.getImageType();
191  if(oformat_opt.size())//default
192  imageType=oformat_opt[0];
193  if(option_opt.findSubstring("INTERLEAVE=")==option_opt.end()){
194  string theInterleave="INTERLEAVE=";
195  theInterleave+=imgReader.getInterleave();
196  option_opt.push_back(theInterleave);
197  }
198  assert(output_opt.size());
199  imgWriter.open(output_opt[0],imgReader.nrOfCol(),imgReader.nrOfRow(),1,theType,imageType,option_opt);
200  if(colorTable_opt.size()){
201  if(colorTable_opt[0]!="none")
202  imgWriter.setColorTable(colorTable_opt[0]);
203  }
204  else if (imgReader.getColorTable()!=NULL)//copy colorTable from input image
205  imgWriter.setColorTable(imgReader.getColorTable());
206 
207  imgWriter.setProjection(imgReader.getProjection());
208  double gt[6];
209  imgReader.getGeoTransform(gt);
210  imgWriter.setGeoTransform(gt);//ulx,uly,imgReader.getDeltaX(),imgReader.getDeltaY(),0,0);
211 
212  if(nodata_opt.size())
213  imgWriter.GDALSetNoDataValue(nodata_opt[0]);
214 
215  vector<char> writeBuffer(imgWriter.nrOfCol());
216  for(int irow=0;irow<imgReader.nrOfRow();++irow){
217  for(int iband=0;iband<band_opt.size();++iband)
218  imgReader.readData(lineBuffer[iband],irow,band_opt[iband]);
219  for(int icol=0;icol<imgReader.nrOfCol();++icol){
220  bool valid=(operator_opt[0]=="OR")?false:true;
221  unsigned short validValue=data_opt[0];
222  if(min_opt.size()&&max_opt.size()){
223  assert(max_opt.size()==min_opt.size());
224  for(int ivalid=0;ivalid<min_opt.size();++ivalid){
225  bool validBand=false;
226  // for(int iband=0;iband<band_opt.size();++iband){
227  unsigned short theBand=(band_opt.size()==min_opt.size())? ivalid:0;
228  if(lineBuffer[theBand][icol]>=min_opt[ivalid]&&lineBuffer[theBand][icol]<=max_opt[ivalid]){
229  validValue=data_opt[ivalid];
230  validBand=true;
231  }
232  valid=(operator_opt[0]=="OR")?valid||validBand : valid&&validBand;
233  }
234  }
235  else if(min_opt.size()){
236  for(int ivalid=0;ivalid<min_opt.size();++ivalid){
237  bool validBand=false;
238  // for(int iband=0;iband<band_opt.size();++iband){
239  unsigned short theBand=(band_opt.size()==min_opt.size())? ivalid:0;
240  if(lineBuffer[theBand][icol]>=min_opt[ivalid]){
241  validValue=data_opt[ivalid];
242  validBand=true;
243  }
244  valid=(operator_opt[0]=="OR")?valid||validBand : valid&&validBand;
245  }
246  }
247  else if(max_opt.size()){
248  for(int ivalid=0;ivalid<max_opt.size();++ivalid){
249  bool validBand=false;
250  // for(int iband=0;iband<band_opt.size();++iband){
251  unsigned short theBand=(band_opt.size()==max_opt.size())? ivalid:0;
252  if(lineBuffer[theBand][icol]<=max_opt[ivalid]){
253  validValue=data_opt[ivalid];
254  validBand=true;
255  }
256  valid=(operator_opt[0]=="OR")?valid||validBand : valid&&validBand;
257  }
258  }
259  if(valid)
260  writeBuffer[icol]=validValue;
261  else
262  writeBuffer[icol]=nodata_opt[0];
263  }
264  imgWriter.writeData(writeBuffer,irow);
265  progress=(1.0+irow)/imgWriter.nrOfRow();
266  pfnProgress(progress,pszMessage,pProgressArg);
267  }
268 
269  imgReader.close();
270  imgWriter.close();
271 }
STL namespace.
int nrOfCol(void) const
Get the number of columns of this dataset.
Definition: ImgRasterGdal.h:98
void setColorTable(const std::string &filename, int band=0)
Set the color table using an (ASCII) file with 5 columns (value R G B alpha)
int nrOfRow(void) const
Get the number of rows of this dataset.
CPLErr setGeoTransform(double *gt)
Set the geotransform data for this dataset.
bool writeData(T &value, int col, int row, int band=0)
Write a single pixel cell value at a specific column and row for a specific band (all indices start c...
Definition: ImgWriterGdal.h:96
void open(const std::string &filename, const ImgReaderGdal &imgSrc, const std::vector< std::string > &options=std::vector< std::string >())
Open an image for writing, copying image attributes from a source image. Image is directly written to...
GDALDataType getDataType(int band=0) const
Get the GDAL datatype for this dataset.
CPLErr setProjection(const std::string &projection)
Set the projection for this dataset in well known text (wkt) format.
void close(void)
Close the image.
CPLErr GDALSetNoDataValue(double noDataValue, int band=0)
Set the GDAL (internal) no data value for this data set. Only a single no data value per band is supp...