pktools  2.6.3
Processing Kernel for geospatial data
pkcreatect.cc
1 /**********************************************************************
2 pkcreatect.cc: program to create and import colour table to GTiff 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 <iostream>
21 #include "imageclasses/ImgReaderGdal.h"
22 #include "imageclasses/ImgWriterGdal.h"
23 #include "base/Optionpk.h"
24 
25 using namespace std;
26 
27 int main(int argc,char **argv) {
28 
29  short red=-1;
30  short green=-1;
31  short blue=-1;
32 
33  Optionpk<string> input_opt("i", "input", "Input image file");
34  Optionpk<string> output_opt("o", "output", "Output image file");
35  Optionpk<string> legend_opt("l", "legend", "Create legend as png file");
36  Optionpk<short> dim_opt("dim", "dim", "number of columns and rows in legend.", 100);
37  Optionpk<double> min_opt("min", "min", "minimum value", 0);
38  Optionpk<double> max_opt("max", "max", "maximum value", 100);
39  Optionpk<bool> grey_opt("g", "grey", "grey scale", false);
40  Optionpk<string> colorTable_opt("ct", "ct", "color table (file with 5 columns: id R G B ALFA (0: transparent, 255: solid)");
41  Optionpk<string> oformat_opt("of", "oformat", "Output image format (see also gdal_translate). Empty string: inherit from input image", "GTiff");
42  Optionpk<string> option_opt("co", "co", "Creation option for output file. Multiple options can be specified.");
43  Optionpk<string> description_opt("d", "description", "Set image description");
44  Optionpk<bool> verbose_opt("v", "verbose", "verbose", false,2);
45 
46  legend_opt.setHide(1);
47  dim_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  legend_opt.retrieveOption(argc,argv);
54  dim_opt.retrieveOption(argc,argv);
55  min_opt.retrieveOption(argc,argv);
56  max_opt.retrieveOption(argc,argv);
57  grey_opt.retrieveOption(argc,argv);
58  colorTable_opt.retrieveOption(argc,argv);
59  description_opt.retrieveOption(argc,argv);
60  oformat_opt.retrieveOption(argc,argv);
61  option_opt.retrieveOption(argc,argv);
62  verbose_opt.retrieveOption(argc,argv);
63  }
64  catch(string predefinedString){
65  std::cout << predefinedString << std::endl;
66  exit(0);
67  }
68  if(!doProcess){
69  cout << endl;
70  cout << "Usage: pkcreatect -i input.txt -o output [-ct colortable | -min value -max value]" << endl;
71  cout << endl;
72  std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
73  exit(0);//help was invoked, stop processing
74  }
75 
76  GDALColorTable colorTable;
77  GDALColorEntry sEntry;
78  if(colorTable_opt.empty()){
79  sEntry.c4=255;
80  for(int i=min_opt[0];i<=max_opt[0];++i){
81  if(grey_opt[0]){
82  sEntry.c1=255*(i-min_opt[0])/(max_opt[0]-min_opt[0]);
83  sEntry.c2=255*(i-min_opt[0])/(max_opt[0]-min_opt[0]);
84  sEntry.c3=255*(i-min_opt[0])/(max_opt[0]-min_opt[0]);
85  }
86  else{//hot to cold colour ramp
87  sEntry.c1=255;
88  sEntry.c2=255;
89  sEntry.c3=255;
90  double delta=max_opt[0]-min_opt[0];
91  if(i<(min_opt[0]+0.25*delta)){
92  sEntry.c1=0;
93  sEntry.c2=255*4*(i-min_opt[0])/delta;
94  }
95  else if(i<(min_opt[0]+0.5*delta)){
96  sEntry.c1=0;
97  sEntry.c3=255*(1+4*(min_opt[0]+0.25*delta-i)/delta);
98  }
99  else if(i<(min_opt[0]+0.75*delta)){
100  sEntry.c1=255*4*(i-min_opt[0]-0.5*delta)/delta;
101  sEntry.c3=0;
102  }
103  else{
104  sEntry.c2=255*(1+4*(min_opt[0]+0.75*delta-i)/delta);
105  sEntry.c3=0;
106  }
107  }
108  colorTable.SetColorEntry(i,&sEntry);
109  if(output_opt.empty())
110  cout << i << " " << sEntry.c1 << " " << sEntry.c2 << " " << sEntry.c3 << " " << sEntry.c4 << endl;
111  }
112  }
113  ImgWriterGdal legendWriter;
114  short ncol=dim_opt[0];
115  short nrow;
116  if(legend_opt.size()){
117  if(dim_opt.size()>1)
118  nrow=dim_opt[1];
119  else{
120  nrow=max_opt[0]-min_opt[0]+1;
121  ncol=dim_opt[0];
122  }
123  vector<string> pngOption;
124  // pngOption.push_back("-co worldfile=no");
125  pngOption.push_back("");
126  legendWriter.open(legend_opt[0],ncol,nrow,1,GDT_Byte,oformat_opt[0],option_opt);
127  if(colorTable_opt.size()){
128  if(colorTable_opt[0]!="none")
129  legendWriter.setColorTable(colorTable_opt[0]);
130  }
131  else
132  legendWriter.setColorTable(&colorTable);
133  if(legend_opt.size()){
134  for(int irow=0;irow<legendWriter.nrOfRow();++irow){
135  vector<char> buffer(legendWriter.nrOfCol());
136  for(int icol=0;icol<legendWriter.nrOfCol();++icol)
137  buffer[icol]=min_opt[0]+irow*static_cast<short>(max_opt[0]-min_opt[0]+1)/legendWriter.nrOfRow();
138  legendWriter.writeData(buffer,GDT_Byte,legendWriter.nrOfRow()-1-irow);
139  }
140  }
141  }
142 
143  // const char* pszMessage;
144  // void* pProgressArg=NULL;
145  // GDALProgressFunc pfnProgress=GDALTermProgress;
146  // double progress=0;
147  // pfnProgress(progress,pszMessage,pProgressArg);
148  if(input_opt.size()&&output_opt.size()){
149  ImgReaderGdal imgReader(input_opt[0]);
150  ImgWriterGdal imgWriter;
151  if(option_opt.findSubstring("INTERLEAVE=")==option_opt.end()){
152  string theInterleave="INTERLEAVE=";
153  theInterleave+=imgReader.getInterleave();
154  option_opt.push_back(theInterleave);
155  }
156 
157  imgWriter.open(output_opt[0],imgReader.nrOfCol(),imgReader.nrOfRow(),1,GDT_Byte,oformat_opt[0],option_opt);
158 
159  imgWriter.copyGeoTransform(imgReader);
160  if(colorTable_opt.size()){
161  if(colorTable_opt[0]!="none")
162  imgWriter.setColorTable(colorTable_opt[0]);
163  }
164  else
165  imgWriter.setColorTable(&colorTable);
166  if(description_opt.size())
167  imgWriter.setImageDescription(description_opt[0]);
168  switch(imgReader.getDataType()){
169  case(GDT_Byte):{
170  vector<char> buffer;
171  for(int irow=0;irow<imgReader.nrOfRow();++irow){
172  imgReader.readData(buffer,GDT_Byte,irow);
173  imgWriter.writeData(buffer,GDT_Byte,irow);
174  }
175  break;
176  }
177  case(GDT_Int16):{
178  vector<short> buffer;
179  cout << "Warning: copying short to unsigned short without conversion, use gdal_translate -scale if needed..." << endl;
180  for(int irow=0;irow<imgReader.nrOfRow();++irow){
181  imgReader.readData(buffer,GDT_Int16,irow,0);
182  imgWriter.writeData(buffer,GDT_Int16,irow,0);
183  }
184  break;
185  }
186  case(GDT_UInt16):{
187  vector<unsigned short> buffer;
188  for(int irow=0;irow<imgReader.nrOfRow();++irow){
189  imgReader.readData(buffer,GDT_UInt16,irow,0);
190  imgWriter.writeData(buffer,GDT_UInt16,irow,0);
191  }
192  break;
193  }
194  default:
195  cerr << "data type " << imgReader.getDataType() << " not supported for adding a colortable" << endl;
196  break;
197  }
198  imgReader.close();
199  imgWriter.close();
200  }
201  if(legend_opt.size())
202  legendWriter.close();
203 }
204