pktools 2.6.7
Processing Kernel for geospatial data
pkgetmask.cc
1/**********************************************************************
2pkgetmask.cc: program to create mask image based on values in input raster image
3Copyright (C) 2008-2014 Pieter Kempeneers
4
5This file is part of pktools
6
7pktools is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or
10(at your option) any later version.
11
12pktools is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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/******************************************************************************/
71using namespace std;
72int 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}
int nrOfRow(void) const
Get the number of rows of this dataset.
CPLErr setGeoTransform(double *gt)
Set the geotransform data for this dataset.
int nrOfCol(void) const
Get the number of columns of this dataset.
Definition: ImgRasterGdal.h:98
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...
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.
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...
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)
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