r7061: initial property settings
[ctsim.git] / tools / if2.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:          if2.cpp
5 **   Purpose:       Manipulate two image files
6 **   Programmer:    Kevin Rosenberg
7 **   Date Started:  May 2000
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2000 Kevin Rosenberg
11 **
12 **  $Id$
13 **
14 **  This program is free software; you can redistribute it and/or modify
15 **  it under the terms of the GNU General Public License (version 2) as
16 **  published by the Free Software Foundation.
17 **
18 **  This program is distributed in the hope that it will be useful,
19 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 **  GNU General Public License for more details.
22 **
23 **  You should have received a copy of the GNU General Public License
24 **  along with this program; if not, write to the Free Software
25 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 ******************************************************************************/
27
28
29 #include "ct.h"
30 #include "timer.h"
31
32 enum {O_ADD, O_SUB, O_MUL, O_DIVIDE, O_COMP, O_ROW_PLOT, O_COLUMN_PLOT, O_VERBOSE, O_HELP, O_VERSION};
33
34 static struct option my_options[] =
35 {
36   {"add", 0, 0, O_ADD},
37   {"sub", 0, 0, O_SUB},
38   {"multiply", 0, 0, O_MUL},
39   {"divide", 0, 0, O_DIVIDE},
40   {"comp", 0, 0, O_COMP},
41   {"column-plot", 1, 0, O_COLUMN_PLOT},
42   {"row-plot", 1, 0, O_ROW_PLOT},
43   {"verbose", 0, 0, O_VERBOSE},
44   {"help", 0, 0, O_HELP},
45   {"version", 0, 0, O_VERSION},
46   {0, 0, 0, 0}
47 };
48
49 static const char* g_szIdStr = "$Id$";
50
51 void 
52 if2_usage (const char *program)
53 {
54   std::cout << "usage: " << fileBasename(program) << " infile1 infile2 outfile [OPTIONS]\n";
55   std::cout << "Perform functions on two input image files\n";
56   std::cout << std::endl;
57   std::cout << "     infile1            Name of first input IF file\n";
58   std::cout << "     infile2            Name of second input IF file\n";
59   std::cout << "     outfile            Name of output Image or Plot file\n";
60   std::cout << "     --add              Add images\n";
61   std::cout << "     --sub              Subtract image 2 from image 1\n";
62   std::cout << "     --mul              Multiply images\n";
63   std::cout << "     --comp             Compare images\n";
64   std::cout << "     --column-plot n    Plot column\n";
65   std::cout << "     --row-plot n       Plot row\n";
66   std::cout << "     --verbose          Verbose modem\n";
67   std::cout << "     --version          Print version\n";
68   std::cout << "     --help             Print this help message\n";
69 }
70
71 int 
72 if2_main (int argc, char *const argv[])
73 {
74   ImageFile* pim_in1;
75   ImageFile* pim_in2;
76   ImageFile* pim_out = NULL;
77   std::string in_file1;
78   std::string in_file2;
79   std::string strOutFile;
80   int opt_verbose = 0;
81   int opt_add = 0;
82   int opt_sub = 0;
83   int opt_mul = 0;
84   bool opt_divide = false;
85   int opt_comp = 0;
86   bool opt_bImageOutputFile = false;
87   bool opt_bPlotOutputFile = false;
88   int opt_rowPlot = -1;
89   int opt_columnPlot = -1;
90   Timer timerProgram;
91   
92   while (1) {
93     char* endptr;
94     int c = getopt_long (argc, argv, "", my_options, NULL);
95     
96     if (c == -1)
97       break;
98     
99     switch (c) {
100     case O_ADD:
101       opt_add = 1;
102       opt_bImageOutputFile = true;
103       break;
104     case O_SUB :
105       opt_sub = 1;
106       opt_bImageOutputFile = true;
107       break;
108     case O_MUL:
109       opt_mul = 1;
110       opt_bImageOutputFile = true;
111       break;
112     case O_DIVIDE:
113       opt_divide = true;
114       opt_bImageOutputFile = true;
115       break;
116     case O_ROW_PLOT:
117       opt_rowPlot = strtol(optarg, &endptr, 10);
118       if (endptr != optarg + strlen(optarg)) {
119         if2_usage(argv[0]);
120       }
121       opt_bPlotOutputFile = true;
122       break;
123     case O_COLUMN_PLOT:
124       opt_columnPlot = strtol(optarg, &endptr, 10);
125       if (endptr != optarg + strlen(optarg)) {
126         if2_usage(argv[0]);
127       }
128       opt_bPlotOutputFile = true;
129       break;
130     case O_COMP:
131       opt_comp = 1;
132       break;
133     case O_VERBOSE:
134       opt_verbose = 1;
135       break;
136     case O_VERSION:
137 #ifdef VERSION
138       std::cout << "Version " << VERSION << std::endl << g_szIdStr << std::endl;
139 #else
140       std::cout << "Unknown version number\n";
141 #endif
142       return (0);
143     case O_HELP:
144     case '?':
145       if2_usage(argv[0]);
146       return (0);
147     default:
148       if2_usage(argv[0]);
149       return (1);
150     }
151   }
152   
153   if ((opt_bImageOutputFile || opt_bPlotOutputFile) && (optind + 3 != argc)) {
154     if2_usage(argv[0]);
155     return (1);
156   }
157   else if (! (opt_bImageOutputFile || opt_bPlotOutputFile) && optind + 2 != argc) {
158     if2_usage(argv[0]);
159     return (1);
160   }
161   
162   in_file1 = argv[optind];
163   in_file2 = argv[optind + 1];
164   if (opt_bImageOutputFile || opt_bPlotOutputFile)
165     strOutFile = argv[optind + 2];
166   
167   pim_in1 = new ImageFile ();
168   pim_in2 = new ImageFile ();
169   ImageFile& im_in1 = *pim_in1;
170   ImageFile& im_in2 = *pim_in2;
171   
172   if (! im_in1.fileRead(in_file1) || ! im_in2.fileRead(in_file2)) {
173     sys_error (ERR_WARNING, "Error reading an image");
174     return (1);
175   }
176   
177   if (im_in1.nx() != im_in2.nx() || im_in1.ny() != im_in2.ny()) {
178     sys_error (ERR_SEVERE, "Error: Size of image 1 (%d,%d) and image 2 (%d,%d) do not match",
179       im_in1.nx(), im_in1.ny(), im_in2.nx(), im_in2.ny());
180     return(1);
181   }
182   if (im_in1.nx() < 0 || im_in1.ny() < 0) {
183     sys_error (ERR_SEVERE, "Error: Size of image < 0");
184     return(1);
185   }
186   
187   ImageFileArray v1 = im_in1.getArray();
188   ImageFileArray v2 = im_in2.getArray();
189   ImageFileArray vout = NULL;
190   
191   if (opt_bImageOutputFile && opt_bPlotOutputFile) {
192     sys_error (ERR_SEVERE, "Both Image and Plot output files can not be selected simultaneously");
193     return (1);
194   }
195   if (opt_bImageOutputFile) {
196     pim_out = new ImageFile (im_in1.nx(), im_in1.ny());
197     vout = pim_out->getArray();
198   }
199   
200   std::string strOperation;
201   int nx = im_in1.nx();
202   int ny = im_in1.ny();
203   int nx2 = im_in2.nx();
204   int ny2 = im_in2.ny();
205   
206   if (opt_add) {
207     strOperation = "Add Images";
208     im_in1.addImages (im_in2, *pim_out);
209   } else if (opt_sub) {
210     strOperation = "Subtract Images";
211     im_in1.subtractImages (im_in2, *pim_out);
212   } else if (opt_mul) {
213     strOperation = "Multiply Images";
214     im_in1.multiplyImages (im_in2, *pim_out);
215   } else if (opt_divide) {
216     strOperation = "Divide Images";
217     im_in1.divideImages (im_in2, *pim_out);
218   }
219   if (opt_comp) {
220     double d, r, e;
221     im_in1.comparativeStatistics (im_in2, d, r, e);
222     std::cout << "d=" << d << ", r=" << r << ", e=" << e << std::endl;
223   }
224   
225   int i;
226   if (opt_columnPlot > 0) {
227     if (opt_columnPlot >= nx || opt_columnPlot >= nx2) {
228       sys_error (ERR_SEVERE, "column-plot > nx");
229       return (1);
230     }
231     double* plot_xaxis = new double [nx];
232     for (i = 0; i < nx; i++)
233       plot_xaxis[i] = i;
234     
235     PlotFile plotFile (3, nx);
236     
237     plotFile.addColumn (0, plot_xaxis);
238     plotFile.addColumn (1, v1[opt_columnPlot]);
239     plotFile.addColumn (2, v2[opt_columnPlot]);
240     std::ostringstream os;
241     os << "Column " << opt_columnPlot << " Comparison";
242     plotFile.addDescription (os.str().c_str());
243     std::string title("title ");
244     title += os.str();
245     plotFile.addEzsetCommand (title.c_str());
246     plotFile.addEzsetCommand ("xlabel Column");
247     plotFile.addEzsetCommand ("ylabel Pixel Value");
248     plotFile.addEzsetCommand ("box");
249     plotFile.addEzsetCommand ("grid");
250     plotFile.addEzsetCommand ("xticks major 5");
251
252     plotFile.fileWrite (strOutFile.c_str());
253     
254     delete plot_xaxis;
255   }
256   
257   if (opt_rowPlot > 0) {
258     if (opt_rowPlot >= ny || opt_rowPlot >= ny2) {
259       sys_error (ERR_SEVERE, "row_plot > ny");
260       return (1);
261     }
262     double* plot_xaxis = new double [ny];
263     double* v1Row = new double [ny];
264     double* v2Row = new double [ny2];
265     
266     for (i = 0; i < ny; i++)
267       plot_xaxis[i] = i;
268     for (i = 0; i < ny; i++)
269       v1Row[i] = v1[i][opt_rowPlot];
270     for (i = 0; i < ny2; i++)
271       v2Row[i] = v2[i][opt_rowPlot];
272     
273     PlotFile plotFile (3, ny);
274     
275     plotFile.addColumn (0, plot_xaxis);
276     plotFile.addColumn (1, v1Row);
277     plotFile.addColumn (2, v2Row);
278     std::ostringstream os;
279     os << "Row " << opt_rowPlot << " Comparison";
280     plotFile.addDescription (os.str().c_str());
281     std::string title("title ");
282     title += os.str();
283     plotFile.addEzsetCommand (title.c_str());
284     plotFile.addEzsetCommand ("xlabel Row");
285     plotFile.addEzsetCommand ("ylabel Pixel Value");
286     plotFile.addEzsetCommand ("box");
287     plotFile.addEzsetCommand ("grid");
288     plotFile.addEzsetCommand ("xticks major 5");
289     
290     plotFile.fileWrite (strOutFile.c_str());
291     
292     delete plot_xaxis;
293     delete v1Row;
294     delete v2Row;
295   }
296   
297   if (opt_bImageOutputFile) {
298     pim_out->labelsCopy (im_in1, "if2 file 1: ");
299     pim_out->labelsCopy (im_in2, "if2 file 2: ");
300     pim_out->labelAdd (Array2dFileLabel::L_HISTORY, strOperation.c_str(), timerProgram.timerEnd());
301     pim_out->fileWrite (strOutFile);
302   }
303   
304   return (0);
305 }
306
307 #ifndef NO_MAIN
308 int 
309 main (int argc, char *const argv[])
310 {
311   int retval = 1;
312   
313   try {
314     retval = if2_main(argc, argv);
315   } catch (exception e) {
316     std::cerr << "Exception: " << e.what() << std::endl;
317   } catch (...) {
318     std::cerr << "Unknown exception\n";
319   }
320   
321   return (retval);
322 }
323 #endif
324