db92c228aee511cbc53b788b4f0e65539f5a4db7
[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: if2.cpp,v 1.3 2000/12/19 21:37:51 kevin Exp $
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_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   {"mul", 0, 0, O_MUL},
39   {"comp", 0, 0, O_COMP},
40   {"column-plot", 1, 0, O_COLUMN_PLOT},
41   {"row-plot", 1, 0, O_ROW_PLOT},
42   {"verbose", 0, 0, O_VERBOSE},
43   {"help", 0, 0, O_HELP},
44   {"version", 0, 0, O_VERSION},
45   {0, 0, 0, 0}
46 };
47
48 static const char* g_szIdStr = "$Id: if2.cpp,v 1.3 2000/12/19 21:37:51 kevin Exp $";
49
50 void 
51 if2_usage (const char *program)
52 {
53   std::cout << "usage: " << fileBasename(program) << " infile1 infile2 outfile [OPTIONS]\n";
54   std::cout << "Perform functions on two input image files\n";
55   std::cout << std::endl;
56   std::cout << "     infile1            Name of first input IF file\n";
57   std::cout << "     infile2            Name of second input IF file\n";
58   std::cout << "     outfile            Name of output Image or Plot file\n";
59   std::cout << "     --add              Add images\n";
60   std::cout << "     --sub              Subtract image 2 from image 1\n";
61   std::cout << "     --mul              Multiply images\n";
62   std::cout << "     --comp             Compare images\n";
63   std::cout << "     --column-plot n    Plot column\n";
64   std::cout << "     --row-plot n       Plot row\n";
65   std::cout << "     --verbose          Verbose modem\n";
66   std::cout << "     --version          Print version\n";
67   std::cout << "     --help             Print this help message\n";
68 }
69
70 int 
71 if2_main (int argc, char *const argv[])
72 {
73   ImageFile* pim_in1;
74   ImageFile* pim_in2;
75   ImageFile* pim_out = NULL;
76   std::string in_file1;
77   std::string in_file2;
78   std::string strOutFile;
79   int opt_verbose = 0;
80   int opt_add = 0;
81   int opt_sub = 0;
82   int opt_mul = 0;
83   int opt_comp = 0;
84   bool opt_bImageOutputFile = false;
85   bool opt_bPlotOutputFile = false;
86   int opt_rowPlot = -1;
87   int opt_columnPlot = -1;
88   Timer timerProgram;
89
90   while (1) {
91     char* endptr;
92     int c = getopt_long (argc, argv, "", my_options, NULL);
93       
94     if (c == -1)
95       break;
96       
97     switch (c) {
98     case O_ADD:
99       opt_add = 1;
100       opt_bImageOutputFile = true;
101       break;
102     case O_SUB :
103       opt_sub = 1;
104       opt_bImageOutputFile = true;
105       break;
106     case O_MUL:
107       opt_mul = 1;
108       opt_bImageOutputFile = true;
109       break;
110     case O_ROW_PLOT:
111       opt_rowPlot = strtol(optarg, &endptr, 10);
112       if (endptr != optarg + strlen(optarg)) {
113         if2_usage(argv[0]);
114       }
115       opt_bPlotOutputFile = true;
116       break;
117     case O_COLUMN_PLOT:
118       opt_columnPlot = strtol(optarg, &endptr, 10);
119       if (endptr != optarg + strlen(optarg)) {
120         if2_usage(argv[0]);
121       }
122       opt_bPlotOutputFile = true;
123       break;
124     case O_COMP:
125       opt_comp = 1;
126       break;
127     case O_VERBOSE:
128       opt_verbose = 1;
129       break;
130     case O_VERSION:
131 #ifdef VERSION
132       std::cout << "Version " << VERSION << std::endl << g_szIdStr << std::endl;
133 #else
134       std::cout << "Unknown version number\n";
135 #endif
136       return (0);
137     case O_HELP:
138     case '?':
139       if2_usage(argv[0]);
140       return (0);
141     default:
142       if2_usage(argv[0]);
143       return (1);
144     }
145   }
146
147   if ((opt_bImageOutputFile || opt_bPlotOutputFile) && (optind + 3 != argc)) {
148     if2_usage(argv[0]);
149     return (1);
150   }
151   else if (! (opt_bImageOutputFile || opt_bPlotOutputFile) && optind + 2 != argc) {
152     if2_usage(argv[0]);
153     return (1);
154   }
155   
156   in_file1 = argv[optind];
157   in_file2 = argv[optind + 1];
158   if (opt_bImageOutputFile || opt_bPlotOutputFile)
159     strOutFile = argv[optind + 2];
160
161   pim_in1 = new ImageFile ();
162   pim_in2 = new ImageFile ();
163   ImageFile& im_in1 = *pim_in1;
164   ImageFile& im_in2 = *pim_in2;
165
166   if (! im_in1.fileRead(in_file1) || ! im_in2.fileRead(in_file2)) {
167       sys_error (ERR_WARNING, "Error reading an image");
168       return (1);
169   }
170
171   if (im_in1.nx() != im_in2.nx() || im_in1.ny() != im_in2.ny()) {
172     sys_error (ERR_SEVERE, "Error: Size of image 1 (%d,%d) and image 2 (%d,%d) do not match",
173             im_in1.nx(), im_in1.ny(), im_in2.nx(), im_in2.ny());
174     return(1);
175   }
176   if (im_in1.nx() < 0 || im_in1.ny() < 0) {
177       sys_error (ERR_SEVERE, "Error: Size of image < 0");
178       return(1);
179   }
180
181   ImageFileArray v1 = im_in1.getArray();
182   ImageFileArray v2 = im_in2.getArray();
183   ImageFileArray vout = NULL;
184
185   if (opt_bImageOutputFile && opt_bPlotOutputFile) {
186     sys_error (ERR_SEVERE, "Both Image and Plot output files can not be selected simultaneously");
187     return (1);
188   }
189   if (opt_bImageOutputFile) {
190     pim_out = new ImageFile (im_in1.nx(), im_in1.ny());
191     vout = pim_out->getArray();
192   }
193
194   std::string strOperation;
195   int nx = im_in1.nx();
196   int ny = im_in1.ny();
197   int nx2 = im_in2.nx();
198   int ny2 = im_in2.ny();
199
200   if (opt_add) {
201     strOperation = "Add Images";
202     for (int ix = 0; ix < nx; ix++) {
203       ImageFileColumn in1 = v1[ix];
204       ImageFileColumn in2 = v2[ix];
205       ImageFileColumn out = vout[ix];
206       for (int iy = 0; iy < ny; iy++)
207         *out++ = *in1++ + *in2++;
208     }
209   } else if (opt_sub) {
210     strOperation = "Subtract Images";
211     for (int ix = 0; ix < nx; ix++) {
212       ImageFileColumn in1 = v1[ix];
213       ImageFileColumn in2 = v2[ix];
214       ImageFileColumn out = vout[ix];
215       for (int iy = 0; iy < ny; iy++)
216           *out++ = *in1++ - *in2++;
217     }
218   } else if (opt_mul) {
219     strOperation = "Multiply Images";
220     for (int ix = 0; ix < nx; ix++) {
221       ImageFileColumn in1 = v1[ix];
222       ImageFileColumn in2 = v2[ix];
223       ImageFileColumn out = vout[ix];
224       for (int iy = 0; iy < ny; iy++)
225         *out++ = *in1++ * *in2++;
226     }
227   }
228   if (opt_comp) {
229     double d, r, e;
230     im_in1.comparativeStatistics (im_in2, d, r, e);
231     std::cout << "d=" << d << ", r=" << r << ", e=" << e << std::endl;
232   }
233 \r
234   int i;
235   if (opt_columnPlot > 0) {
236     if (opt_columnPlot >= nx || opt_columnPlot >= nx2) {
237       sys_error (ERR_SEVERE, "column-plot > nx");
238       return (1);
239     }
240     double* plot_xaxis = new double [nx];
241     for (i = 0; i < nx; i++)
242       plot_xaxis[i] = i;
243 \r
244     PlotFile plotFile (3, nx);\r
245 \r
246     plotFile.addColumn (0, plot_xaxis);\r
247     plotFile.addColumn (1, v1[opt_columnPlot]);\r
248     plotFile.addColumn (2, v2[opt_columnPlot]);\r
249     plotFile.setTitle ("Column Plot");\r
250     plotFile.setXLabel ("Column");\r
251     plotFile.setYLabel ("Pixel Value");\r
252 \r
253     plotFile.fileWrite (strOutFile.c_str());\r
254 \r
255 #if HAVE_SGP
256     SGPDriver driver ("Column Plot");
257     SGP sgp (driver);
258     EZPlot ezplot (sgp);
259     ezplot.ezset ("clear.");
260     ezplot.ezset ("xticks major 5.");
261     ezplot.ezset ("xlabel Column");
262     ezplot.ezset ("title Column Plot");
263     ezplot.ezset ("ylabel Pixel");
264     ezplot.ezset ("box.");
265     ezplot.ezset ("grid.");
266     ezplot.addCurve (plot_xaxis, v1[opt_columnPlot], im_in1.ny());
267     ezplot.addCurve (plot_xaxis, v2[opt_columnPlot], im_in2.ny());
268     ezplot.plot();
269     std::cout << "Press enter to continue" << flush;
270     cio_kb_getc();
271 #endif
272     delete plot_xaxis;
273   }
274
275   if (opt_rowPlot > 0) {
276     if (opt_rowPlot >= ny || opt_rowPlot >= ny2) {
277       sys_error (ERR_SEVERE, "row_plot > ny");
278       return (1);
279     }
280     double* plot_xaxis = new double [ny];
281     double* v1Row = new double [ny];\r
282         double* v2Row = new double [ny2];
283
284     for (i = 0; i < ny; i++)
285       plot_xaxis[i] = i;
286     for (i = 0; i < ny; i++)
287       v1Row[i] = v1[i][opt_rowPlot];
288     for (i = 0; i < ny2; i++)
289       v2Row[i] = v2[i][opt_rowPlot];
290
291     PlotFile plotFile (3, ny);
292
293     plotFile.addColumn (0, plot_xaxis);
294     plotFile.addColumn (1, v1Row);
295     plotFile.addColumn (2, v2Row);
296     plotFile.setTitle ("Row Plot");
297     plotFile.setXLabel ("Row");
298     plotFile.setYLabel ("Pixel Value");
299
300     plotFile.fileWrite (strOutFile.c_str());
301
302 #if HAVE_SGP
303     SGPDriver driver ("Row Plot");
304     SGP sgp (driver);
305     EZPlot ezplot (sgp);
306     ezplot.ezset ("clear.");
307     ezplot.ezset ("xticks major 5.");
308     ezplot.ezset ("title Row Plot");
309     ezplot.ezset ("xlabel Row");
310     ezplot.ezset ("ylabel Pixel");
311     ezplot.ezset ("box.");
312     ezplot.ezset ("grid.");
313     ezplot.addCurve (plot_xaxis, v1Row, im_in1.nx());
314     ezplot.addCurve (plot_xaxis, v2Row, im_in2.nx());
315     ezplot.plot();
316     std::cout << "Press enter to continue" << flush;
317     cio_kb_getc();
318 #endif
319         delete plot_xaxis;\r
320         delete v1Row;\r
321         delete v2Row;\r
322   }
323
324   if (opt_bImageOutputFile) {
325     pim_out->labelsCopy (im_in1, "if2 file 1: ");
326     pim_out->labelsCopy (im_in2, "if2 file 2: ");
327     pim_out->labelAdd (Array2dFileLabel::L_HISTORY, strOperation.c_str(), timerProgram.timerEnd());
328     pim_out->fileWrite (strOutFile);
329   }
330 \r
331   return (0);
332 }
333
334 #ifndef NO_MAIN
335 int 
336 main (int argc, char *const argv[])
337 {
338   int retval = 1;
339
340   try {
341     retval = if2_main(argc, argv);
342   } catch (exception e) {
343     std::cerr << "Exception: " << e.what() << std::endl;
344   } catch (...) {
345     std::cerr << "Unknown exception\n";
346   }
347
348   return (retval);
349 }
350 #endif
351