Change arguments to --focus; add implementation for d3::focus::add_region().
[Ale.git] / ale.cc
blob648944ee74cec844708ced38a0b027897659d205
1 // Copyright 2002, 2003 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * ale.cc: The main loop of ALE, including the user interface.
26 * ANSI C and POSIX include files.
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <assert.h>
33 #include <time.h>
34 #include <math.h>
37 * Types
40 #include "ale_pos.h"
41 #include "ale_real.h"
44 * Interface files
47 #include "ui/ui.h"
48 #include "unsupported.h"
49 #include "implication.h"
52 * 2D include files
55 #include "d2.h"
58 * 3D include files
61 #include "d3.h"
64 * Device configuration files
67 #include "device/xvp610_320x240.h"
68 #include "device/xvp610_640x480.h"
69 #include "device/ov7620_raw_linear.h"
70 #include "device/canon_300d_raw_linear.h"
71 #include "device/canon_300d_raw_linear_85mm_1_8.h"
72 #include "device/canon_300d_raw_linear_50mm_1_8.h"
73 #include "device/canon_300d_raw_linear_50mm_1_4.h"
74 #include "device/canon_300d_raw_linear_50mm_1_4_1_4.h"
77 * Help files
80 #include "help.h"
83 * Version Information
86 char *short_version = "0.8.3";
88 char *version = "ALE Version: 0.8.3\n"
89 #ifdef USE_MAGICK
90 "File handler: ImageMagick\n"
91 #else
92 "File handler: PPM\n"
93 #endif
94 "Color data: " ALE_REAL_PRECISION_STRING "\n"
95 "Coordinate data: " ALE_POS_PRECISION_STRING "\n"
96 #ifdef USE_FFTW
97 "DFT: FFTW3\n"
98 #else
99 "DFT: Built-in\n"
100 #endif
101 #if defined NDEBUG && !defined DEBUG
102 "Assertions: Disabled\n"
103 #elif defined DEBUG && !defined NDEBUG
104 "Assertions: Enabled\n"
105 #elif defined NDEBUG
106 "Assertions: Probably disabled\n"
107 #else
108 "Assertions: Probably enabled\n"
109 #endif
110 #if OPTIMIZATIONS == 1
111 "Optimizations: Enabled\n"
112 #else
113 "Optimizations: Disabled\n"
114 #endif
118 * Argument counter.
120 * Counts instances of a given option.
122 unsigned int arg_count(int argc, const char *argv[], const char *arg) {
123 unsigned int count = 0;
124 for (int i = 0; i < argc; i++) {
125 if (!strcmp(argv[i], arg))
126 count++;
127 else if (!strcmp(argv[i], "--"))
128 return count;
130 return count;
134 * Argument prefix counter.
136 * Counts instances of a given option prefix.
138 unsigned int arg_prefix_count(int argc, const char *argv[], const char *pfix) {
139 unsigned int count = 0;
140 for (int i = 0; i < argc; i++) {
141 if (!strncmp(argv[i], pfix, strlen(pfix)))
142 count++;
143 else if (!strcmp(argv[i], "--"))
144 return count;
146 return count;
150 * Reallocation function
152 void *local_realloc(void *ptr, size_t size) {
153 void *new_ptr = realloc(ptr, size);
155 if (new_ptr == NULL)
156 ui::get()->memory_error_location("main()");
158 return new_ptr;
162 * Not enough arguments function.
164 void not_enough(const char *opt_name) {
165 ui::get()->cli_not_enough(opt_name);
169 * Bad argument function
171 void bad_arg(const char *opt_name) {
172 ui::get()->cli_bad_arg(opt_name);
176 * Main function.
178 * Does one of two things:
180 * (1) Output version information if called with '--version'
182 * (2) Read options and file arguments, and if the arguments are correct,
183 * write output. If an error is detected, print the usage statement.
187 int main(int argc, const char *argv[]){
190 * Initialize help object
193 help hi(argv[0], short_version);
196 * Output version information if --version appears
197 * on the command line.
200 if (arg_count(argc, argv, "--version")) {
202 * Output the version
205 fprintf(stdout, "%s", version);
207 return 0;
211 * Handle help options
214 if (arg_prefix_count(argc, argv, "--h"))
215 for (int i = 1; i < argc; i++) {
216 int all = !strcmp(argv[i], "--hA");
217 int is_help_option = !strncmp(argv[i], "--h", strlen("--h"));
218 int found_help = 0;
220 if (!strcmp(argv[i], "--hu") || all)
221 hi.usage(), found_help = 1;
222 if (!strcmp(argv[i], "--hq") || all)
223 hi.defaults(), found_help = 1;
224 if (!strcmp(argv[i], "--hf") || all)
225 hi.file(), found_help = 1;
226 if (!strcmp(argv[i], "--he") || all)
227 hi.exclusion(), found_help = 1;
228 if (!strcmp(argv[i], "--ha") || all)
229 hi.alignment(), found_help = 1;
230 if (!strcmp(argv[i], "--hr") || all)
231 hi.rendering(), found_help = 1;
232 if (!strcmp(argv[i], "--hx") || all)
233 hi.exposure(), found_help = 1;
234 if (!strcmp(argv[i], "--ht") || all)
235 hi.tdf(), found_help = 1;
236 if (!strcmp(argv[i], "--hl") || all)
237 hi.filtering(), found_help = 1;
238 if (!strcmp(argv[i], "--hd") || all)
239 hi.device(), found_help = 1;
240 if (!strcmp(argv[i], "--hi") || all)
241 hi.interface(), found_help = 1;
242 if (!strcmp(argv[i], "--hv") || all)
243 hi.visp(), found_help = 1;
244 if (!strcmp(argv[i], "--hc") || all)
245 hi.cp(), found_help = 1;
246 if (!strcmp(argv[i], "--h3") || all)
247 hi.d3(), found_help = 1;
248 if (!strcmp(argv[i], "--hz") || all)
249 hi.undocumented(), found_help = 1;
251 if (is_help_option && !found_help)
252 hi.usage();
255 * Check for the end-of-options marker, a non-option argument,
256 * or the end of arguments. In all of these cases, we exit.
259 if (!strcmp(argv[i], "--")
260 || strncmp(argv[i], "--", strlen("--"))
261 || i == argc - 1)
262 return 0;
266 * Undocumented projective transformation utility
269 if (arg_count(argc, argv, "--ptcalc") > 0) {
270 fprintf(stderr, "\n\n*** Warning: this feature is not documented ***\n\n");
271 printf("Enter: w h tlx tly blx bly brx bry trx try x y\n\n");
273 double w, h, tlx, tly, blx, bly, brx, bry, trx, tr_y, x, y;
275 printf("> ");
277 if (scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
278 &w, &h, &tlx, &tly, &blx, &bly, &brx, &bry, &trx, &tr_y, &x, &y) != 12) {
280 fprintf(stderr, "Error reading input.\n");
281 exit(1);
284 d2::image *i = new d2::image_ale_real((int)h, (int)w, 3);
285 d2::transformation t = d2::transformation::gpt_identity(i, 1);
286 d2::point q[4] = {
287 d2::point(tly, tlx),
288 d2::point(bly, blx),
289 d2::point(bry, brx),
290 d2::point(tr_y, trx)
292 t.gpt_set(q);
294 d2::point a(y, x), b;
296 b = t.transform_scaled(a);
298 printf("TRANSFORM t(a): (%f, %f)\n", (double) b[1], (double) b[0]);
300 b = t.scaled_inverse_transform(a);
302 printf("INVERSE t^-1(a): (%f, %f)\n", (double) b[1], (double) b[0]);
304 exit(0);
308 * Flags and variables
311 double scale_factor = 1;
312 double vise_scale_factor = 1;
313 #if 0
314 double usm_multiplier = 0.0;
315 #endif
316 int extend = 0;
317 struct d2::tload_t *tload = NULL;
318 struct d2::tsave_t *tsave = NULL;
319 struct d3::tload_t *d3_tload = NULL;
320 struct d3::tsave_t *d3_tsave = NULL;
321 int ip_iterations = 0;
322 int ip_use_median = 0;
323 enum { psf_linear, psf_nonlinear, psf_N };
324 const char *psf[psf_N] = {NULL, NULL};
325 const char *device = NULL;
326 int psf_match = 0;
327 double psf_match_args[6];
328 int inc = 1;
329 int exposure_register = 1;
330 const char *wm_filename = NULL;
331 int wm_offsetx, wm_offsety;
332 double cx_parameter = 0;
333 double *d3px_parameters = NULL;
334 int d3px_count = 0;
335 int *ex_parameters = NULL;
336 int ex_count = 0;
337 int ex_show = 0;
338 d2::render *achain;
339 const char *achain_type = "triangle:2";
340 const char *afilter_type = "internal";
341 d2::render **ochain = NULL;
342 const char **ochain_names = NULL;
343 const char **ochain_types = NULL;
344 const char *d3chain_type = NULL;
345 int oc_count = 0;
346 const char **visp = NULL;
347 int vise_count = 0;
348 const char **d3_output = NULL;
349 const char **d3_depth = NULL;
350 unsigned int d3_count = 0;
351 double user_view_angle = 0;
352 int user_bayer = IMAGE_BAYER_DEFAULT;
353 d2::pixel exp_mult = d2::pixel(1, 1, 1);
354 std::map<const char *, d3::pt> d3_output_pt;
355 std::map<const char *, d3::pt> d3_depth_pt;
358 * dchain is ochain[0].
361 ochain = (d2::render **) local_realloc(ochain,
362 (oc_count + 1) * sizeof(d2::render *));
363 ochain_names = (const char **) local_realloc((void *)ochain_names,
364 (oc_count + 1) * sizeof(const char *));
365 ochain_types = (const char **) local_realloc((void *)ochain_types,
366 (oc_count + 1) * sizeof(const char *));
368 ochain_types[0] = "sinc*lanc:8";
370 oc_count = 1;
373 * Handle default settings
376 if (arg_prefix_count(argc, argv, "--q") > 1)
377 ui::get()->error("more than one default setting option --q* was specified");
379 if (arg_count(argc, argv, "--q0")) {
380 ochain_types[0] = "fine:box:1,triangle:2";
381 achain_type = "triangle:2";
382 d2::align::mc(0.3);
383 ip_iterations = 0;
384 d2::image_rw::exp_noscale();
385 cx_parameter = 0;
386 } else if (arg_count(argc, argv, "--qn")) {
387 ochain_types[0] = "sinc*lanc:6";
388 achain_type = "sinc*lanc:6";
389 d2::align::mc(0.5);
390 ip_iterations = 0;
391 d2::image_rw::exp_noscale();
392 cx_parameter = 0;
393 } else if (arg_count(argc, argv, "--q1")) {
394 ochain_types[0] = "median:fine:sinc*lanc:8,triangle:2";
395 achain_type = "triangle:2";
396 d2::align::mc(0.5);
397 ip_iterations = 0;
398 d2::image_rw::exp_noscale();
399 cx_parameter = 0;
400 } else if (arg_count(argc, argv, "--q2")) {
401 ochain_types[0] = "sinc*lanc:8";
402 achain_type = "sinc*lanc:8";
403 d2::align::no_mc();
404 ip_iterations = 4;
405 d2::image_rw::exp_noscale();
406 cx_parameter = 0;
407 } else if (arg_count(argc, argv, "--qr")) {
408 ochain_types[0] = "sinc*lanc:8";
409 achain_type = "sinc*lanc:8";
410 d2::align::no_mc();
411 ip_iterations = 6;
412 d2::image_rw::exp_scale();
413 cx_parameter = 0.7;
414 } else {
416 * Same as --q0
418 ochain_types[0] = "fine:box:1,triangle:2";
419 achain_type = "triangle:2";
420 d2::align::mc(0.3);
421 ip_iterations = 0;
422 d2::image_rw::exp_noscale();
423 cx_parameter = 0;
427 * Set default d3chain to default ochain[0].
430 d3chain_type = ochain_types[0];
433 * Iterate through arguments until we reach the first file
434 * argument. After the first file argument, we assume that
435 * all following arguments are files.
438 for (int i = 1; i < argc - 1; i++) {
441 if (!strcmp(argv[i], "--q0")
442 || !strcmp(argv[i], "--q1")
443 || !strcmp(argv[i], "--q2")
444 || !strcmp(argv[i], "--qr")
445 || !strcmp(argv[i], "--qn")) {
447 * Do nothing. Defaults have already been set.
449 } else if (!strcmp(argv[i], "--8bpc")) {
450 d2::image_rw::depth8();
451 } else if (!strcmp(argv[i], "--16bpc")) {
452 d2::image_rw::depth16();
453 } else if (!strcmp(argv[i], "--plain")) {
454 d2::image_rw::ppm_plain();
455 } else if (!strcmp(argv[i], "--raw")) {
456 d2::image_rw::ppm_raw();
457 } else if (!strcmp(argv[i], "--auto")) {
458 d2::image_rw::ppm_auto();
459 } else if (!strcmp(argv[i], "--align-all")) {
460 d2::align::all();
461 } else if (!strcmp(argv[i], "--align-green")) {
462 d2::align::green();
463 } else if (!strcmp(argv[i], "--align-sum")) {
464 d2::align::sum();
465 } else if (!strcmp(argv[i], "--translation")) {
466 d2::align::class_translation();
467 } else if (!strcmp(argv[i], "--euclidean")) {
468 d2::align::class_euclidean();
469 } else if (!strcmp(argv[i], "--projective")) {
470 d2::align::class_projective();
471 } else if (!strcmp(argv[i], "--identity")) {
472 d2::align::initial_default_identity();
473 } else if (!strcmp(argv[i], "--follow")) {
474 d2::align::initial_default_follow();
475 } else if (!strcmp(argv[i], "--perturb-output")) {
476 d2::align::perturb_output();
477 } else if (!strcmp(argv[i], "--perturb-source")) {
478 d2::align::perturb_source();
479 } else if (!strcmp(argv[i], "--fail-optimal")) {
480 d2::align::fail_optimal();
481 } else if (!strcmp(argv[i], "--fail-default")) {
482 d2::align::fail_default();
483 } else if (!strcmp(argv[i], "--no-extend")) {
484 extend = 0;
485 } else if (!strcmp(argv[i], "--extend")) {
486 extend = 1;
487 } else if (!strcmp(argv[i], "--no-mc")) {
488 d2::align::no_mc();
489 } else if (!strcmp(argv[i], "--oc")) {
490 d3::scene::oc();
491 } else if (!strcmp(argv[i], "--no-oc")) {
492 d3::scene::no_oc();
493 } else if (!strcmp(argv[i], "--gs")) {
494 if (i + 1 >= argc)
495 not_enough("--gs");
497 d2::align::gs(argv[i+1]);
498 i += 1;
500 } else if (!strcmp(argv[i], "--gs-mo")) {
501 if (i + 1 >= argc)
502 not_enough("--gs-mo");
504 unsigned int mo_parameter;
505 if (sscanf(argv[i+1], "%u", &mo_parameter) != 1)
506 bad_arg("--gs-mo");
508 d2::align::gs_mo(mo_parameter);
509 i += 1;
511 } else if (!strcmp(argv[i], "--focus")) {
514 * Check for argument availability
517 if (i + 7 >= argc)
518 not_enough(argv[i]);
520 unsigned int ci;
521 double sd, ed, fd, cc, df, vt, ht;
523 if (sscanf(argv[i+1], "%u", &ci) != 1
524 || sscanf(argv[i+2], "%lf", &sd) != 1
525 || sscanf(argv[i+3], "%lf", &ed) != 1
526 || sscanf(argv[i+4], "%lf", &fd) != 1
527 || sscanf(argv[i+5], "%lf", &cc) != 1
528 || sscanf(argv[i+6], "%lf", &df) != 1
529 || sscanf(argv[i+7], "%lf", &vt) != 1
530 || sscanf(argv[i+8], "%lf", &ht) != 1)
531 bad_arg(argv[i]);
533 d3::focus::add_region(ci, sd, ed, fd, cc, df, vt, ht);
535 i+=8;
536 } else if (!strcmp(argv[i], "--3ddp") || !strcmp(argv[i], "--3dvp")) {
537 d2::align::keep();
540 * Unsupported configurations
543 if (ip_iterations)
544 unsupported::fornow("3D modeling with Irani-Peleg rendering");
546 #if 0
547 if (usm_multiplier)
548 unsupported::fornow("3D modeling with unsharp mask");
549 #endif
552 * Check for argument availability
555 if (i + 10 >= argc)
556 not_enough(argv[i]);
559 * Initialize if necessary
561 * Note: because their existence is checked as an
562 * indicator of the presence of 3D arguments, we
563 * initialize these structures here.
566 if (d3_output == NULL) {
567 d3_count = argc - (i + 2) - 1;
568 d3_output = (const char **) calloc(d3_count, sizeof(char *));
569 d3_depth = (const char **) calloc(d3_count, sizeof(char *));
572 unsigned int width, height;
573 double view_angle;
574 double x, y, z;
575 double P, Y, R;
577 if (sscanf(argv[i+1], "%u", &width) != 1
578 || sscanf(argv[i+2], "%u", &height) != 1
579 || sscanf(argv[i+3], "%lf", &view_angle) != 1
580 || sscanf(argv[i+4], "%lf", &x) != 1
581 || sscanf(argv[i+5], "%lf", &y) != 1
582 || sscanf(argv[i+6], "%lf", &z) != 1
583 || sscanf(argv[i+7], "%lf", &P) != 1
584 || sscanf(argv[i+8], "%lf", &Y) != 1
585 || sscanf(argv[i+9], "%lf", &R) != 1)
586 bad_arg(argv[i]);
588 view_angle *= M_PI / 180;
589 P *= M_PI / 180;
590 Y *= M_PI / 180;
591 R *= M_PI / 180;
593 d2::transformation t =
594 d2::transformation::eu_identity();
595 t.set_domain(height, width);
596 d3::pt _pt(t, d3::et(y, x, z, Y, P, R), view_angle);
598 if (!strcmp(argv[i], "--3dvp")) {
599 d3_output_pt[argv[i+10]] = _pt;
600 } else if (!strcmp(argv[i], "--3ddp")) {
601 d3_depth_pt[argv[i+10]] = _pt;
602 } else {
603 assert(0);
606 i+=10;
607 } else if (!strcmp(argv[i], "--3dv")) {
608 d2::align::keep();
610 unsigned int frame_no;
613 * Unsupported configurations
616 if (ip_iterations)
617 unsupported::fornow("3D modeling with Irani-Peleg rendering");
619 #if 0
620 if (usm_multiplier)
621 unsupported::fornow("3D modeling with unsharp mask");
622 #endif
625 * Check for argument availability
628 if (i + 2 >= argc)
629 not_enough("--3dv");
632 * Initialize if necessary
635 if (d3_output == NULL) {
636 d3_count = argc - (i + 2) - 1;
637 d3_output = (const char **) calloc(d3_count, sizeof(char *));
638 d3_depth = (const char **) calloc(d3_count, sizeof(char *));
641 if (sscanf(argv[i+1], "%d", &frame_no) != 1)
642 ui::get()->error("--3dv argument 0 must be an integer");
644 if (frame_no >= d3_count)
645 ui::get()->error("--3dv argument 0 is too large");
647 if (d3_output[frame_no] != NULL) {
648 unsupported::fornow ("Writing a single 3D view to more than one output file");
651 d3_output[frame_no] = argv[i+2];
653 i+=2;
654 } else if (!strcmp(argv[i], "--3dd")) {
655 d2::align::keep();
657 unsigned int frame_no;
660 * Unsupported configurations
663 if (ip_iterations)
664 unsupported::fornow("3D modeling with Irani-Peleg rendering");
666 #if 0
667 if (usm_multiplier)
668 unsupported::fornow("3D modeling with unsharp mask");
669 #endif
672 * Check for argument availability
675 if (i + 2 >= argc)
676 not_enough("--3dd");
679 * Initialize if necessary
682 if (d3_output == NULL) {
683 d3_count = argc - (i + 2) - 1;
684 d3_output = (const char **) calloc(d3_count, sizeof(char *));
685 d3_depth = (const char **) calloc(d3_count, sizeof(char *));
688 if (sscanf(argv[i+1], "%d", &frame_no) != 1)
689 ui::get()->error("--3dd argument 0 must be an integer");
691 if (frame_no >= d3_count)
692 ui::get()->error("--3dd argument 0 is too large");
694 if (d3_depth[frame_no] != NULL) {
695 unsupported::fornow ("Writing a single frame's depth info to more than one output file");
698 d3_depth[frame_no] = argv[i+2];
700 i+=2;
702 } else if (!strcmp(argv[i], "--view-angle")) {
703 if (i + 1 >= argc)
704 not_enough("--view-angle");
706 double va_parameter;
707 sscanf(argv[i+1], "%lf", &va_parameter);
708 i += 1;
709 user_view_angle = va_parameter * M_PI / 180;
710 } else if (!strcmp(argv[i], "--cpf-load")) {
711 if (i + 1 >= argc)
712 not_enough("--cpf-load");
714 d3::cpf::init_loadfile(argv[i+1]);
715 i += 1;
716 } else if (!strcmp(argv[i], "--ui=stream")) {
717 ui::set_stream();
718 } else if (!strcmp(argv[i], "--ui=tty")) {
719 ui::set_tty();
720 } else if (!strcmp(argv[i], "--3d-fmr")) {
722 if (i + 1 >= argc)
723 not_enough("--3d-fmr");
725 double fmr_parameter;
726 sscanf(argv[i+1], "%lf", &fmr_parameter);
727 i += 1;
728 d3::scene::fmr(fmr_parameter);
730 } else if (!strcmp(argv[i], "--3d-dmr")) {
732 if (i + 1 >= argc)
733 not_enough("--3d-dmr");
735 double dmr_parameter;
736 sscanf(argv[i+1], "%lf", &dmr_parameter);
737 i += 1;
738 d3::scene::dmr(dmr_parameter);
740 } else if (!strcmp(argv[i], "--et")) {
742 if (i + 1 >= argc)
743 not_enough("--et");
745 double et_parameter;
746 sscanf(argv[i+1], "%lf", &et_parameter);
747 i += 1;
748 d3::scene::et(et_parameter);
750 } else if (!strcmp(argv[i], "--st")) {
751 if (i + 1 >= argc)
752 not_enough("--st");
754 double st_parameter;
755 sscanf(argv[i+1], "%lf", &st_parameter);
756 i += 1;
757 d3::cpf::st(st_parameter);
758 } else if (!strcmp(argv[i], "--di-lower")) {
759 if (i + 1 >= argc)
760 not_enough("--di-lower");
762 double di_parameter;
763 sscanf(argv[i+1], "%lf", &di_parameter);
764 i += 1;
765 d3::scene::di_lower(di_parameter);
766 } else if (!strcmp(argv[i], "--rc")) {
767 if (i + 1 >= argc)
768 not_enough("--rc");
770 double rc_parameter;
771 sscanf(argv[i+1], "%lf", &rc_parameter);
772 i += 1;
773 d3::scene::rc(rc_parameter);
774 } else if (!strcmp(argv[i], "--do-try")) {
775 if (i + 1 >= argc)
776 not_enough("--do-try");
778 double do_parameter;
779 sscanf(argv[i+1], "%lf", &do_parameter);
780 i += 1;
781 d3::scene::do_try(do_parameter);
782 } else if (!strcmp(argv[i], "--di-upper")) {
783 if (i + 1 >= argc)
784 not_enough("--di-upper");
786 double dgi_parameter;
787 sscanf(argv[i+1], "%lf", &dgi_parameter);
788 i += 1;
789 d3::scene::di_upper(dgi_parameter);
790 } else if (!strcmp(argv[i], "--fc")) {
791 if (i + 1 >= argc)
792 not_enough("--fc");
794 double fc_parameter;
795 sscanf(argv[i+1], "%lf", &fc_parameter);
796 i += 1;
797 d3::scene::fc(fc_parameter);
798 } else if (!strcmp(argv[i], "--ecm")) {
799 unsupported::discontinued("--ecm <x>");
800 } else if (!strcmp(argv[i], "--acm")) {
801 unsupported::discontinued("--acm <x>");
802 } else if (!strcmp(argv[i], "--def-nn")) {
803 if (i + 1 >= argc)
804 not_enough("--def-nn");
806 double nn_parameter;
807 sscanf(argv[i+1], "%lf", &nn_parameter);
808 i += 1;
809 d2::image_rw::def_nn(nn_parameter);
811 if (nn_parameter > 2) {
812 fprintf(stderr, "\n\n*** Warning: --def-nn implementation is currently "
813 "inefficient for large radii. ***\n\n");
816 } else if (!strcmp(argv[i], "--mc")) {
817 if (i + 1 >= argc)
818 not_enough("--mc");
820 double mc_parameter;
821 sscanf(argv[i+1], "%lf", &mc_parameter);
822 mc_parameter /= 100;
823 i += 1;
824 d2::align::mc(mc_parameter);
826 } else if (!strcmp(argv[i], "--fx")) {
828 if (i + 1 >= argc)
829 not_enough("--fx");
831 double fx_parameter;
832 sscanf(argv[i+1], "%lf", &fx_parameter);
833 i += 1;
834 d3::scene::fx(fx_parameter);
836 } else if (!strcmp(argv[i], "--tcem")) {
838 if (i + 1 >= argc)
839 not_enough("--tcem");
841 double tcem_parameter;
842 sscanf(argv[i+1], "%lf", &tcem_parameter);
843 i += 1;
844 d3::scene::tcem(tcem_parameter);
846 } else if (!strcmp(argv[i], "--oui")) {
848 if (i + 1 >= argc)
849 not_enough("--oui");
851 unsigned int oui_parameter;
852 sscanf(argv[i+1], "%u", &oui_parameter);
853 i += 1;
854 d3::scene::oui(oui_parameter);
856 } else if (!strcmp(argv[i], "--pa")) {
858 if (i + 1 >= argc)
859 not_enough("--pa");
861 unsigned int pa_parameter;
862 sscanf(argv[i+1], "%u", &pa_parameter);
863 i += 1;
864 d3::scene::pa(pa_parameter);
866 } else if (!strcmp(argv[i], "--pc")) {
868 if (i + 1 >= argc)
869 not_enough("--pc");
871 d3::scene::pc(argv[i+1]);
872 i += 1;
874 } else if (!strcmp(argv[i], "--cw")) {
875 d2::align::certainty_weighted(1);
876 } else if (!strcmp(argv[i], "--no-cw")) {
877 d2::align::certainty_weighted(0);
878 } else if (!strcmp(argv[i], "--wm")) {
879 if (wm_filename != NULL)
880 ui::get()->error("only one weight map can be specified");
882 if (i + 3 >= argc)
883 not_enough("--wm");
884 wm_filename = argv[i+1];
886 if (sscanf(argv[i+2], "%d", &wm_offsetx) != 1)
887 ui::get()->error("--wm x-argument must be an integer");
889 if (sscanf(argv[i+3], "%d", &wm_offsety) != 1)
890 ui::get()->error("--wm y-argument must be an integer");
892 i += 3;
894 } else if (!strcmp(argv[i], "--fl")) {
895 if (i + 3 >= argc)
896 not_enough("--fl");
897 double h, v, a;
898 if (sscanf(argv[i+1], "%lf", &h) != 1)
899 ui::get()->error("--fl h-argument must be numerical");
900 if (sscanf(argv[i+2], "%lf", &v) != 1)
901 ui::get()->error("--fl v-argument must be numerical");
902 if (sscanf(argv[i+3], "%lf", &a) != 1)
903 ui::get()->error("--fl a-argument must be numerical");
904 i += 3;
905 #ifdef USE_FFTW
906 d2::align::set_frequency_cut(h, v, a);
907 #else
908 ui::get()->error_hint("--fl is not supported", "rebuild ALE with FFTW=1");
909 #endif
910 } else if (!strcmp(argv[i], "--wmx")) {
911 if (i + 3 >= argc)
912 not_enough("--wmx");
913 #ifdef USE_UNIX
914 d2::align::set_wmx(argv[i+1], argv[i+2], argv[i+3]);
915 #else
916 ui::get()->error_hint("--wmx is not supported", "rebuild ALE with POSIX=1");
917 #endif
918 i += 3;
919 } else if (!strcmp(argv[i], "--flshow")) {
920 if (i + 1 >= argc)
921 not_enough("--flshow");
922 d2::align::set_fl_show(argv[i+1]);
923 i++;
924 } else if (!strcmp(argv[i], "--3dpx")) {
925 if (i + 6 >= argc)
926 not_enough("--3dpx");
928 d3px_parameters = (double *) local_realloc(d3px_parameters, (d3px_count + 1) * 6 * sizeof(double));
930 for (int param = 0; param < 6; param++)
931 if (sscanf(argv[i + param + 1], "%lf", &(d3px_parameters[6 * d3px_count + param])) != 1)
932 bad_arg("--d3px");
935 * Swap x and y, since their internal meanings differ from their external meanings.
938 for (int param = 0; param < 2; param++) {
939 double temp = d3px_parameters[6 * d3px_count + 2 + param];
940 d3px_parameters[6 * d3px_count + 2 + param] = d3px_parameters[6 * d3px_count + 0 + param];
941 d3px_parameters[6 * d3px_count + 0 + param] = temp;
946 * Increment counters
949 d3px_count++;
950 i += 6;
951 } else if (!strcmp(argv[i], "--ex")) {
952 if (i + 6 >= argc)
953 not_enough("--ex");
955 ex_parameters = (int *) local_realloc(ex_parameters, (ex_count + 1) * 6 * sizeof(int));
957 for (int param = 0; param < 6; param++)
958 if (sscanf(argv[i + param + 1], "%d", &(ex_parameters[6 * ex_count + param])) != 1)
959 bad_arg("--ex");
962 * Swap x and y, since their internal meanings differ from their external meanings.
965 for (int param = 0; param < 2; param++) {
966 int temp = ex_parameters[6 * ex_count + 2 + param];
967 ex_parameters[6 * ex_count + 2 + param] = ex_parameters[6 * ex_count + 0 + param];
968 ex_parameters[6 * ex_count + 0 + param] = temp;
973 * Increment counters
976 ex_count++;
977 i += 6;
978 } else if (!strcmp(argv[i], "--crop")) {
979 if (i + 6 >= argc)
980 not_enough("--crop");
982 ex_parameters = (int *) local_realloc(ex_parameters, (ex_count + 4) * 6 * sizeof(int));
983 int crop_args[6];
985 for (int param = 0; param < 6; param++)
986 if (sscanf(argv[i + param + 1], "%d", &(crop_args[param])) != 1)
987 bad_arg("--crop");
990 * Construct exclusion regions from the crop area,
991 * swapping x and y, since their internal meanings
992 * differ from their external meanings.
996 * Exclusion region 1: low x
999 ex_parameters[6 * ex_count + 0] = INT_MIN;
1000 ex_parameters[6 * ex_count + 1] = crop_args[2] - 1;
1001 ex_parameters[6 * ex_count + 2] = INT_MIN;
1002 ex_parameters[6 * ex_count + 3] = INT_MAX;
1003 ex_parameters[6 * ex_count + 4] = crop_args[4];
1004 ex_parameters[6 * ex_count + 5] = crop_args[5];
1007 * Exclusion region 2: low y
1010 ex_parameters[6 * ex_count + 6] = INT_MIN;
1011 ex_parameters[6 * ex_count + 7] = INT_MAX;
1012 ex_parameters[6 * ex_count + 8] = INT_MIN;
1013 ex_parameters[6 * ex_count + 9] = crop_args[0] - 1;
1014 ex_parameters[6 * ex_count + 10] = crop_args[4];
1015 ex_parameters[6 * ex_count + 11] = crop_args[5];
1018 * Exclusion region 3: high y
1021 ex_parameters[6 * ex_count + 12] = INT_MIN;
1022 ex_parameters[6 * ex_count + 13] = INT_MAX;
1023 ex_parameters[6 * ex_count + 14] = crop_args[1] + 1;
1024 ex_parameters[6 * ex_count + 15] = INT_MAX;
1025 ex_parameters[6 * ex_count + 16] = crop_args[4];
1026 ex_parameters[6 * ex_count + 17] = crop_args[5];
1029 * Exclusion region 4: high x
1032 ex_parameters[6 * ex_count + 18] = crop_args[3] + 1;
1033 ex_parameters[6 * ex_count + 19] = INT_MAX;
1034 ex_parameters[6 * ex_count + 20] = INT_MIN;
1035 ex_parameters[6 * ex_count + 21] = INT_MAX;
1036 ex_parameters[6 * ex_count + 22] = crop_args[4];
1037 ex_parameters[6 * ex_count + 23] = crop_args[5];
1040 * Increment counters
1043 ex_count += 4;
1044 i += 6;
1045 } else if (!strcmp(argv[i], "--exshow")) {
1046 ex_show = 1;
1047 } else if (!strcmp(argv[i], "--wt")) {
1048 if (i + 1 >= argc)
1049 not_enough("--wt");
1051 double wt;
1053 if (sscanf(argv[i + 1], "%lf", &wt) != 1)
1054 bad_arg("--wt");
1056 d2::render::set_wt(wt);
1057 i++;
1058 } else if (!strcmp(argv[i], "--3d-chain")) {
1059 if (i + 1 >= argc)
1060 not_enough("--3d-chain");
1061 d3chain_type = argv[i+1];
1062 i++;
1063 } else if (!strcmp(argv[i], "--dchain")) {
1064 if (i + 1 >= argc)
1065 not_enough("--dchain");
1066 ochain_types[0] = argv[i+1];
1067 i++;
1068 } else if (!strcmp(argv[i], "--achain")) {
1069 if (i + 1 >= argc)
1070 not_enough("--achain");
1071 achain_type = argv[i+1];
1072 i++;
1073 } else if (!strcmp(argv[i], "--afilter")) {
1074 if (i + 1 >= argc)
1075 not_enough("--afilter");
1076 afilter_type = argv[i+1];
1077 i++;
1078 } else if (!strcmp(argv[i], "--ochain")) {
1079 if (i + 2 >= argc)
1080 not_enough("--ochain");
1082 ochain = (d2::render **) local_realloc(ochain,
1083 (oc_count + 1) * sizeof(d2::render *));
1084 ochain_names = (const char **) local_realloc((void *)ochain_names,
1085 (oc_count + 1) * sizeof(const char *));
1086 ochain_types = (const char **) local_realloc((void *)ochain_types,
1087 (oc_count + 1) * sizeof(const char *));
1089 ochain_types[oc_count] = argv[i+1];
1090 ochain_names[oc_count] = argv[i+2];
1092 oc_count++;
1093 i+=2;
1094 } else if (!strcmp(argv[i], "--visp")) {
1095 if (i + 5 >= argc)
1096 not_enough("--visp");
1098 visp = (const char **) local_realloc((void *)visp, 4 *
1099 (vise_count + 1) * sizeof(const char *));
1101 for (int param = 0; param < 4; param++)
1102 visp[vise_count * 4 + param] = argv[i + 1 + param];
1104 vise_count++;
1105 i+=4;
1106 } else if (!strcmp(argv[i], "--cx")) {
1108 if (i + 1 >= argc)
1109 not_enough("--cx");
1111 sscanf(argv[i+1], "%lf", &cx_parameter);
1112 i += 1;
1114 } else if (!strcmp(argv[i], "--no-cx")) {
1115 cx_parameter = 0;
1116 } else if (!strcmp(argv[i], "--ip")) {
1117 unsupported::discontinued("--ip <r> <i>", "--lpsf box=<r> --ips <i>");
1118 } else if (!strcmp(argv[i], "--bayer")) {
1119 if (i + 1 >= argc)
1120 not_enough("--bayer");
1123 * External order is clockwise from top-left. Internal
1124 * order is counter-clockwise from top-left.
1127 if (!strcmp(argv[i+1], "rgbg")) {
1128 user_bayer = IMAGE_BAYER_RGBG;
1129 } else if (!strcmp(argv[i+1], "bgrg")) {
1130 user_bayer = IMAGE_BAYER_BGRG;
1131 } else if (!strcmp(argv[i+1], "gbgr")) {
1132 user_bayer = IMAGE_BAYER_GRGB;
1133 } else if (!strcmp(argv[i+1], "grgb")) {
1134 user_bayer = IMAGE_BAYER_GBGR;
1135 } else if (!strcmp(argv[i+1], "none")) {
1136 user_bayer = IMAGE_BAYER_NONE;
1137 } else {
1138 bad_arg("--bayer");
1140 i++;
1141 } else if (!strcmp(argv[i], "--lpsf")) {
1142 if (i + 1 >= argc)
1143 not_enough("--lpsf");
1145 psf[psf_linear] = argv[i+1];
1146 i++;
1147 } else if (!strcmp(argv[i], "--nlpsf")) {
1148 if (i + 1 >= argc)
1149 not_enough("--nlpsf");
1151 psf[psf_nonlinear] = argv[i+1];
1152 i++;
1154 } else if (!strcmp(argv[i], "--psf-match")) {
1155 if (i + 6 >= argc)
1156 not_enough("--psf-match");
1158 psf_match = 1;
1160 for (int index = 0; index < 6; index++) {
1161 if (sscanf(argv[i + 1], "%lf", &psf_match_args[index]) != 1)
1162 bad_arg("--psf-match");
1163 i++;
1166 } else if (!strcmp(argv[i], "--device")) {
1167 if (i + 1 >= argc)
1168 not_enough("--device");
1170 device = argv[i+1];
1171 i++;
1173 #if 0
1174 } else if (!strcmp(argv[i], "--usm")) {
1176 if (d3_output != NULL)
1177 unsupported::fornow("3D modeling with unsharp mask");
1179 if (i + 1 >= argc)
1180 not_enough("--usm");
1182 sscanf(argv[i+1], "%lf", &usm_multiplier);
1183 i++;
1184 #endif
1186 } else if (!strcmp(argv[i], "--ipr")) {
1188 if (i + 1 >= argc)
1189 not_enough("--ipr");
1191 if (sscanf(argv[i+1], "%d", &ip_iterations) != 1)
1192 ui::get()->error("--ipr requires an integer argument");
1194 ui::get()->warn("--ipr is deprecated. Use --ips instead");
1195 i++;
1197 } else if (!strcmp(argv[i], "--cpp-err-median")) {
1198 d3::cpf::err_median();
1199 } else if (!strcmp(argv[i], "--cpp-err-mean")) {
1200 d3::cpf::err_mean();
1201 } else if (!strcmp(argv[i], "--vp-adjust")) {
1202 d3::align::vp_adjust();
1203 } else if (!strcmp(argv[i], "--vp-noadjust")) {
1204 d3::align::vp_noadjust();
1205 } else if (!strcmp(argv[i], "--vo-adjust")) {
1206 d3::align::vo_adjust();
1207 } else if (!strcmp(argv[i], "--vo-noadjust")) {
1208 d3::align::vo_noadjust();
1209 } else if (!strcmp(argv[i], "--ip-mean")) {
1210 ip_use_median = 0;
1211 } else if (!strcmp(argv[i], "--ip-median")) {
1212 ip_use_median = 1;
1213 } else if (!strcmp(argv[i], "--ips")) {
1215 if (i + 1 >= argc)
1216 not_enough("--ips");
1218 if (sscanf(argv[i+1], "%d", &ip_iterations) != 1)
1219 ui::get()->error("--ips requires an integer argument");
1220 i++;
1221 } else if (!strcmp(argv[i], "--ipc")) {
1222 unsupported::discontinued("--ipc <c> <i>", "--ips <i> --lpsf <c>", "--ips <i> --device <c>");
1223 } else if (!strcmp(argv[i], "--exp-extend")) {
1224 d2::image_rw::exp_scale();
1225 } else if (!strcmp(argv[i], "--exp-noextend")) {
1226 d2::image_rw::exp_noscale();
1227 } else if (!strcmp(argv[i], "--exp-register")) {
1228 exposure_register = 1;
1229 d2::align::exp_register();
1230 } else if (!strcmp(argv[i], "--exp-noregister")) {
1231 exposure_register = 0;
1232 d2::align::exp_noregister();
1233 } else if (!strcmp(argv[i], "--exp-meta-only")) {
1234 exposure_register = 2;
1235 d2::align::exp_meta_only();
1236 } else if (!strcmp(argv[i], "--drizzle-only")) {
1237 unsupported::discontinued("--drizzle-only", "--dchain box:1");
1238 } else if (!strcmp(argv[i], "--subspace-traverse")) {
1239 unsupported::undocumented("--subspace-traverse");
1240 d3::scene::set_subspace_traverse();
1241 } else if (!strcmp(argv[i], "--3d-nofilter")) {
1242 d3::scene::filter();
1243 } else if (!strcmp(argv[i], "--3d-filter")) {
1244 d3::scene::nofilter();
1245 } else if (!strcmp(argv[i], "--occ-norm")) {
1246 d3::scene::nw();
1247 } else if (!strcmp(argv[i], "--occ-nonorm")) {
1248 d3::scene::no_nw();
1249 } else if (!strcmp(argv[i], "--inc")) {
1250 inc = 1;
1251 } else if (!strcmp(argv[i], "--no-inc")) {
1252 inc = 0;
1253 } else if (!strncmp(argv[i], "--exp-mult=", strlen("--exp-mult="))) {
1254 double exp_c, exp_r, exp_b;
1255 sscanf(argv[i] + strlen("--exp-mult="), "%lf,%lf,%lf", &exp_c, &exp_r, &exp_b);
1256 exp_mult = d2::pixel(1/(exp_r * exp_c), 1/exp_c, 1/(exp_b * exp_c));
1257 } else if (!strncmp(argv[i], "--visp-scale=", strlen("--visp-scale="))) {
1259 sscanf(argv[i] + strlen("--visp-scale="), "%lf", &vise_scale_factor);
1261 if (vise_scale_factor <= 0.0)
1262 ui::get()->error("VISP scale must be greater than zero");
1264 if (!finite(vise_scale_factor))
1265 ui::get()->error("VISP scale must be finite");
1267 } else if (!strncmp(argv[i], "--scale=", strlen("--scale="))) {
1269 sscanf(argv[i] + strlen("--scale="), "%lf", &scale_factor);
1271 if (scale_factor <= 0)
1272 ui::get()->error("Scale factor must be greater than zero");
1274 if (!finite(scale_factor))
1275 ui::get()->error("Scale factor must be finite");
1277 } else if (!strncmp(argv[i], "--metric=", strlen("--metric="))) {
1278 double metric;
1279 sscanf(argv[i] + strlen("--metric="), "%lf", &metric);
1280 d2::align::set_metric_exponent(metric);
1281 } else if (!strncmp(argv[i], "--threshold=", strlen("--threshold="))) {
1282 double match_threshold;
1283 sscanf(argv[i] + strlen("--threshold="), "%lf", &match_threshold);
1284 d2::align::set_match_threshold(match_threshold);
1285 } else if (!strncmp(argv[i], "--drizzle-diam=", strlen("--drizzle-diam="))) {
1286 unsupported::discontinued("--drizzle-diam=<x>", "--dchain box:1");
1287 // sscanf(argv[i] + strlen("--drizzle-diam="), "%lf", &drizzle_radius);
1288 // drizzle_radius /= 2;
1289 } else if (!strncmp(argv[i], "--perturb-upper=", strlen("--perturb-upper="))) {
1290 double perturb_upper;
1291 int characters;
1292 sscanf(argv[i] + strlen("--perturb-upper="), "%lf%n", &perturb_upper,
1293 &characters);
1294 if (*(argv[i] + strlen("--perturb-upper=") + characters) == '%')
1295 d2::align::set_perturb_upper(perturb_upper, 1);
1296 else
1297 d2::align::set_perturb_upper(perturb_upper, 0);
1298 } else if (!strncmp(argv[i], "--perturb-lower=", strlen("--perturb-lower="))) {
1299 double perturb_lower;
1300 int characters;
1301 sscanf(argv[i] + strlen("--perturb-lower="), "%lf%n", &perturb_lower,
1302 &characters);
1303 if (perturb_lower <= 0)
1304 ui::get()->error("--perturb-lower= value is non-positive");
1306 if (*(argv[i] + strlen("--perturb-lower=") + characters) == '%')
1307 d2::align::set_perturb_lower(perturb_lower, 1);
1308 else
1309 d2::align::set_perturb_lower(perturb_lower, 0);
1310 } else if (!strncmp(argv[i], "--stepsize=", strlen("--stepsize="))) {
1311 double perturb_lower;
1312 ui::get()->warn("--stepsize is deprecated. Use --perturb-lower instead");
1313 sscanf(argv[i] + strlen("--stepsize="), "%lf", &perturb_lower);
1314 d2::align::set_perturb_lower(perturb_lower, 0);
1315 } else if (!strncmp(argv[i], "--va-upper=", strlen("--va-upper="))) {
1316 double va_upper;
1317 int characters;
1318 sscanf(argv[i] + strlen("--va-upper="), "%lf%n", &va_upper,
1319 &characters);
1320 if (*(argv[i] + strlen("--va-upper=") + characters) == '%')
1321 ui::get()->error("--va-upper= does not accept '%' arguments\n");
1322 else
1323 d3::cpf::set_va_upper(va_upper);
1324 } else if (!strncmp(argv[i], "--cpp-upper=", strlen("--cpp-upper="))) {
1325 double perturb_upper;
1326 int characters;
1327 sscanf(argv[i] + strlen("--cpp-upper="), "%lf%n", &perturb_upper,
1328 &characters);
1329 if (*(argv[i] + strlen("--cpp-upper=") + characters) == '%')
1330 ui::get()->error("--cpp-upper= does not currently accept '%' arguments\n");
1331 else
1332 d3::cpf::set_cpp_upper(perturb_upper);
1333 } else if (!strncmp(argv[i], "--cpp-lower=", strlen("--cpp-lower="))) {
1334 double perturb_lower;
1335 int characters;
1336 sscanf(argv[i] + strlen("--cpp-lower="), "%lf%n", &perturb_lower,
1337 &characters);
1338 if (*(argv[i] + strlen("--cpp-lower=") + characters) == '%')
1339 ui::get()->error("--cpp-lower= does not currently accept '%' arguments\n");
1340 else
1341 d3::cpf::set_cpp_lower(perturb_lower);
1342 } else if (!strncmp(argv[i], "--hf-enhance=", strlen("--hf-enhance="))) {
1343 unsupported::discontinued("--hf-enhance=<x>");
1344 } else if (!strncmp(argv[i], "--rot-upper=", strlen("--rot-upper="))) {
1345 double rot_max;
1346 sscanf(argv[i] + strlen("--rot-upper="), "%lf", &rot_max);
1347 d2::align::set_rot_max((int) floor(rot_max));
1348 } else if (!strncmp(argv[i], "--bda-mult=", strlen("--bda-mult="))) {
1349 double bda_mult;
1350 sscanf(argv[i] + strlen("--bda-mult="), "%lf", &bda_mult);
1351 d2::align::set_bda_mult(bda_mult);
1352 } else if (!strncmp(argv[i], "--bda-rate=", strlen("--bda-rate="))) {
1353 double bda_rate;
1354 sscanf(argv[i] + strlen("--bda-rate="), "%lf", &bda_rate);
1355 d2::align::set_bda_rate(bda_rate);
1356 } else if (!strncmp(argv[i], "--lod-max=", strlen("--lod-max="))) {
1357 double lod_max;
1358 sscanf(argv[i] + strlen("--lod-max="), "%lf", &lod_max);
1359 d2::align::set_lod_max((int) floor(lod_max));
1360 } else if (!strncmp(argv[i], "--cpf-load=", strlen("--cpf-load="))) {
1361 d3::cpf::init_loadfile(argv[i] + strlen("--cpf-load="));
1362 #if 0
1363 } else if (!strncmp(argv[i], "--model-load=", strlen("--model-load="))) {
1364 d3::scene::load_model(argv[i] + strlen("--model-load="));
1365 } else if (!strncmp(argv[i], "--model-save=", strlen("--model-save="))) {
1366 d3::scene::save_model(argv[i] + strlen("--model-save="));
1367 #endif
1368 } else if (!strncmp(argv[i], "--trans-load=", strlen("--trans-load="))) {
1369 d2::tload_delete(tload);
1370 tload = d2::tload_new(argv[i] + strlen("--trans-load="));
1371 d2::align::set_tload(tload);
1372 } else if (!strncmp(argv[i], "--trans-save=", strlen("--trans-save="))) {
1373 tsave_delete(tsave);
1374 tsave = d2::tsave_new(argv[i] + strlen("--trans-save="));
1375 d2::align::set_tsave(tsave);
1376 } else if (!strncmp(argv[i], "--3d-trans-load=", strlen("--3d-trans-load="))) {
1377 d3::tload_delete(d3_tload);
1378 d3_tload = d3::tload_new(argv[i] + strlen("--3d-trans-load="));
1379 d3::align::set_tload(d3_tload);
1380 } else if (!strncmp(argv[i], "--3d-trans-save=", strlen("--3d-trans-save="))) {
1381 d3::tsave_delete(d3_tsave);
1382 d3_tsave = d3::tsave_new(argv[i] + strlen("--3d-trans-save="));
1383 d3::align::set_tsave(d3_tsave);
1384 } else {
1387 * Trap illegal options and end-of-option indicators.
1390 if (!strcmp(argv[i], "--"))
1391 i++;
1392 else if (!strncmp(argv[i], "--", strlen("--")))
1393 ui::get()->illegal_option(argv[i]);
1396 * Apply implication logic.
1399 if (extend == 0 && vise_count != 0) {
1400 implication::changed("VISP requires increased image extents.",
1401 "Image extension is now enabled.",
1402 "--extend");
1403 extend = 1;
1406 if (psf_match && ex_count)
1407 unsupported::fornow("PSF calibration with exclusion regions.");
1410 if (d3_output != NULL && ip_iterations != 0)
1411 unsupported::fornow("3D modeling with Irani-Peleg rendering");
1413 #if 0
1414 if (extend == 0 && d3_output != NULL) {
1415 implication::changed("3D modeling requires increased image extents.",
1416 "Image extension is now enabled.",
1417 "--extend");
1418 extend = 1;
1420 #endif
1422 if (cx_parameter != 0 && !exposure_register) {
1423 implication::changed("Certainty-based rendering requires exposure registration.",
1424 "Exposure registration is now enabled.",
1425 "--exp-register");
1426 d2::align::exp_register();
1427 exposure_register = 1;
1431 * Set alignment class exclusion region static variables
1434 d2::align::set_exclusion(ex_parameters, ex_count);
1437 * Initialize renderer class statics.
1440 d2::render::render_init(ex_count, ex_parameters, ex_show, extend, scale_factor);
1443 * Set confidence
1446 d2::exposure::set_confidence(cx_parameter);
1449 * Keep transformations for Irani-Peleg, psf-match, and
1450 * VISE
1453 if (ip_iterations > 0 || psf_match || vise_count > 0) {
1454 d2::align::keep();
1458 * Initialize device-specific variables
1461 d2::psf *device_response[psf_N] = { NULL, NULL };
1462 d2::exposure **input_exposure = NULL;
1463 ale_pos view_angle = 43.7 * M_PI / 180;
1464 // ale_pos view_angle = 90 * M_PI / 180;
1465 input_exposure = (d2::exposure **)
1466 malloc((argc - i - 1) * sizeof(d2::exposure *));
1468 if (device != NULL) {
1469 if (!strcmp(device, "xvp610_640x480")) {
1470 device_response[psf_linear] = new xvp610_640x480::lpsf();
1471 device_response[psf_nonlinear] = new xvp610_640x480::nlpsf();
1472 for (int ii = 0; ii < argc - i - 1; ii++)
1473 input_exposure[ii] = new xvp610_640x480::exposure();
1474 view_angle = xvp610_640x480::view_angle();
1475 } else if (!strcmp(device, "xvp610_320x240")) {
1476 device_response[psf_linear] = new xvp610_320x240::lpsf();
1477 device_response[psf_nonlinear] = new xvp610_320x240::nlpsf();
1478 for (int ii = 0; ii < argc - i - 1; ii++)
1479 input_exposure[ii] = new xvp610_320x240::exposure();
1480 view_angle = xvp610_320x240::view_angle();
1481 } else if (!strcmp(device, "ov7620_raw_linear")) {
1482 device_response[psf_linear] = new ov7620_raw_linear::lpsf();
1483 device_response[psf_nonlinear] = NULL;
1484 for (int ii = 0; ii < argc - i - 1; ii++)
1485 input_exposure[ii] = new ov7620_raw_linear::exposure();
1486 d2::image_rw::set_default_bayer(IMAGE_BAYER_BGRG);
1487 } else if (!strcmp(device, "canon_300d_raw_linear")) {
1488 device_response[psf_linear] = new canon_300d_raw_linear::lpsf();
1489 device_response[psf_nonlinear] = NULL;
1490 for (int ii = 0; ii < argc - i - 1; ii++)
1491 input_exposure[ii] = new canon_300d_raw_linear::exposure();
1492 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1493 } else if (!strcmp(device, "canon_300d_raw_linear+85mm_1.8")) {
1494 device_response[psf_linear] = new canon_300d_raw_linear_85mm_1_8::lpsf();
1495 device_response[psf_nonlinear] = NULL;
1496 for (int ii = 0; ii < argc - i - 1; ii++)
1497 input_exposure[ii] = new canon_300d_raw_linear_85mm_1_8::exposure();
1498 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1499 view_angle = canon_300d_raw_linear_85mm_1_8::view_angle();
1500 } else if (!strcmp(device, "canon_300d_raw_linear+50mm_1.8")) {
1501 device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_8::lpsf();
1502 device_response[psf_nonlinear] = NULL;
1503 for (int ii = 0; ii < argc - i - 1; ii++)
1504 input_exposure[ii] = new canon_300d_raw_linear_50mm_1_8::exposure();
1505 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1506 view_angle = canon_300d_raw_linear_50mm_1_8::view_angle();
1507 } else if (!strcmp(device, "canon_300d_raw_linear+50mm_1.4")) {
1508 device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_4::lpsf();
1509 device_response[psf_nonlinear] = NULL;
1510 for (int ii = 0; ii < argc - i - 1; ii++)
1511 input_exposure[ii] = new canon_300d_raw_linear_50mm_1_4::exposure();
1512 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1513 view_angle = canon_300d_raw_linear_50mm_1_4::view_angle();
1514 } else if (!strcmp(device, "canon_300d_raw_linear+50mm_1.4@1.4")) {
1515 device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_4_1_4::lpsf();
1516 device_response[psf_nonlinear] = NULL;
1517 for (int ii = 0; ii < argc - i - 1; ii++)
1518 input_exposure[ii] = new canon_300d_raw_linear_50mm_1_4_1_4::exposure();
1519 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1520 view_angle = canon_300d_raw_linear_50mm_1_4_1_4::view_angle();
1521 } else {
1522 ui::get()->unknown_device(device);
1524 } else {
1525 for (int ii = 0; ii < argc - i - 1; ii++)
1526 input_exposure[ii] = new d2::exposure_default();
1530 * User-specified variables.
1533 if (user_view_angle != 0) {
1534 view_angle = user_view_angle;
1537 if (user_bayer != IMAGE_BAYER_DEFAULT) {
1538 d2::image_rw::set_default_bayer(user_bayer);
1542 * PSF-match exposure.
1544 if (psf_match) {
1545 delete input_exposure[argc - i - 2];
1546 input_exposure[argc - i - 2] = new d2::exposure_default();
1550 * Initialize output exposure
1553 d2::exposure *output_exposure = new d2::exposure_default();
1554 output_exposure->set_multiplier(exp_mult);
1557 * Configure the response function.
1560 d2::psf *response[2] = {NULL, NULL};
1562 for (int n = 0; n < psf_N; n++ ) {
1563 if (psf[n] != NULL) {
1565 response[n] = d2::psf_parse::get((n == psf_linear), psf[n]);
1567 } else if (device_response[n] != NULL) {
1570 * Device-specific response
1573 response[n] = device_response[n];
1575 } else {
1578 * Default point-spread function.
1581 if (n == psf_linear) {
1584 * Default lpsf is a box filter
1585 * of diameter 1.0 (radius
1586 * 0.5).
1589 response[n] = new d2::box(0.5);
1591 } else if (n == psf_nonlinear) {
1594 * nlpsf is disabled by default.
1597 response[n] = NULL;
1603 * First file argument. Print general file information as well
1604 * as information specific to this argument. Initialize image
1605 * file handler.
1609 * There should be at least two file arguments.
1612 if (i >= argc - 1) {
1613 hi.usage();
1614 exit(1);
1617 d2::image_rw::init(argc - i - 1, argv + i, argv[argc - 1], input_exposure, output_exposure);
1618 ochain_names[0] = argv[argc - 1];
1621 * Handle control point data for alignment
1623 d2::align::set_cp_count(d3::cpf::count());
1624 for (unsigned int ii = 0; ii < d3::cpf::count(); ii++)
1625 d2::align::set_cp(ii, d3::cpf::get_2d(ii));
1628 * PSF-match bayer patterns.
1631 if (psf_match) {
1632 d2::image_rw::set_specific_bayer(argc - i - 2, IMAGE_BAYER_NONE);
1636 * Handle alignment weight map, if necessary
1639 if (wm_filename != NULL) {
1640 d2::image *weight_map;
1641 weight_map = d2::image_rw::read_image(wm_filename, new d2::exposure_linear());
1642 weight_map->set_offset(wm_offsety, wm_offsetx);
1643 d2::align::set_weight_map(weight_map);
1647 * Write comment information about original frame and
1648 * target image to the transformation save file, if we
1649 * have one.
1652 const d2::image *im = d2::image_rw::open(0);
1653 tsave_orig(tsave, argv[i], im->avg_channel_magnitude());
1654 tsave_target(tsave, argv[argc - 1]);
1655 d2::image_rw::close(0);
1658 * Initialize alignment interpolant.
1661 if (afilter_type != "internal")
1662 d2::align::set_interpolant(d2::render_parse::get_SSF(afilter_type));
1665 * Initialize achain and ochain.
1668 achain = d2::render_parse::get(achain_type);
1670 for (int chain = 0; chain < oc_count; chain++)
1671 ochain[chain] = d2::render_parse::get(ochain_types[chain]);
1674 * Use merged renderings as reference images in
1675 * alignment.
1678 d2::align::set_reference(achain);
1681 * Tell the alignment class about the scale factor.
1684 d2::align::set_scale(scale_factor);
1687 * Initialize visp.
1690 d2::vise_core::set_scale(vise_scale_factor);
1692 for (int opt = 0; opt < vise_count; opt++) {
1693 d2::vise_core::add(d2::render_parse::get(visp[opt * 4 + 0]),
1694 visp[opt * 4 + 1],
1695 visp[opt * 4 + 2],
1696 visp[opt * 4 + 3]);
1700 * Initialize non-incremental renderers
1703 #if 0
1704 if (usm_multiplier != 0) {
1707 * Unsharp Mask renderer
1710 ochain[0] = new d2::usm(ochain[0], scale_factor,
1711 usm_multiplier, inc, response[psf_linear],
1712 response[psf_nonlinear], &input_exposure[0]);
1714 #endif
1716 if (psf_match) {
1719 * Point-spread function calibration renderer.
1720 * This renderer does not produce image output.
1721 * It is reserved for use with the point-spread
1722 * function calibration script
1723 * ale-psf-calibrate.
1726 ochain[0] = new d2::psf_calibrate(ochain[0],
1727 1, inc, response[psf_linear],
1728 response[psf_nonlinear],
1729 psf_match_args);
1731 } else if (ip_iterations != 0) {
1734 * Irani-Peleg renderer
1737 ochain[0] = new d2::ipc( ochain[0], ip_iterations,
1738 inc, response[psf_linear],
1739 response[psf_nonlinear],
1740 (exposure_register == 1), ip_use_median);
1744 * Handle the original frame.
1747 ui::get()->original_frame_start(argv[i]);
1749 for (int opt = 0; opt < oc_count; opt++) {
1750 ui::get()->set_orender_current(opt);
1751 ochain[opt]->sync(0);
1752 if (inc) {
1753 ui::get()->writing_output(opt);
1754 d2::image_rw::write_image(ochain_names[opt],
1755 ochain[opt]->get_image(0));
1759 d2::vise_core::frame_queue_add(0);
1761 ui::get()->original_frame_done();
1764 * Handle supplemental frames.
1767 for (unsigned int j = 1; j < d2::image_rw::count(); j++) {
1769 const char *name = d2::image_rw::name(j);
1771 ui::get()->supplemental_frame_start(name);
1774 * Write comment information about the
1775 * supplemental frame to the transformation
1776 * save file, if we have one.
1779 tsave_info (tsave, name);
1781 const d2::image *im = d2::image_rw::open(j);
1782 d2::pixel apm = im->avg_channel_magnitude();
1783 tsave_apm(tsave, apm[0], apm[1], apm[2]);
1784 d2::image_rw::close(j);
1786 for (int opt = 0; opt < oc_count; opt++) {
1787 ui::get()->set_orender_current(opt);
1788 ochain[opt]->sync(j);
1789 if (inc) {
1790 ui::get()->writing_output(opt);
1791 d2::image_rw::write_image(ochain_names[opt],
1792 ochain[opt]->get_image(j));
1796 d2::vise_core::frame_queue_add(j);
1798 ui::get()->supplemental_frame_done();
1802 * Do any post-processing and output final image
1804 * XXX: note that non-incremental renderers currently
1805 * return zero for ochain[0]->sync(), since they write
1806 * output internally when inc != 0.
1809 for (int opt = 0; opt < oc_count; opt++)
1810 if ((ochain[opt]->sync() || !inc) && !psf_match)
1811 d2::image_rw::write_image(ochain_names[opt], ochain[opt]->get_image());
1814 * Output a summary match statistic.
1817 ui::get()->ale_done((double) d2::align::match_summary());
1820 * Perform any 3D tasks
1823 optimizations::begin_3d_work();
1825 if (d3_count > 0) {
1827 d3::align::init_angle(view_angle);
1829 d3::align::init_from_d2();
1831 if (d3::cpf::count() > 0) {
1832 d3::cpf::solve_3d();
1835 d3::align::write_alignments();
1837 d3::scene::set_filter_type(d3chain_type);
1839 d3::scene::init_from_d2();
1841 // d3::scene::add_control_points();
1843 // d3::scene::relax_triangle_model();
1845 d3::scene::make_space(d3_depth, d3_output, &d3_depth_pt, &d3_output_pt);
1847 // fprintf(stderr, "Total pixels: %lu\n", d3::scene::total_pixels);
1848 // fprintf(stderr, "Total ambiguity: %lu\n", d3::scene::total_ambiguity);
1849 // fprintf(stderr, "Total tsteps: %lu\n", d3::scene::total_tsteps);
1850 // fprintf(stderr, "Total divisions: %lu\n", d3::scene::total_divisions);
1852 fprintf(stderr, "Updating occupancy values");
1853 d3::scene::reduce_cost_to_search_depth(output_exposure, inc);
1854 fprintf(stderr, ".\n");
1856 fprintf(stderr, "Writing 3D output");
1857 d3::scene::d3px(d3px_count, d3px_parameters);
1858 int view_count = 0;
1859 for (unsigned int i = 0; i < d2::image_rw::count(); i++) {
1860 assert (i < d3_count);
1862 if (d3_depth[i] != NULL) {
1863 const d2::image *im = d3::scene::depth(i);
1864 d2::image_rw::write_image(d3_depth[i], im, output_exposure, 1, 1);
1865 delete im;
1868 if (d3_output[i] != NULL) {
1869 const d2::image *im = d3::scene::view(i);
1870 d2::image_rw::write_image(d3_output[i], im, output_exposure);
1871 delete im;
1872 d3::focus::set_camera(view_count++);
1875 for (std::map<const char *, d3::pt>::iterator i = d3_output_pt.begin();
1876 i != d3_output_pt.end(); i++) {
1878 const d2::image *im = d3::scene::view(i->second);
1879 d2::image_rw::write_image(i->first, im, output_exposure);
1880 delete im;
1881 d3::focus::set_camera(view_count++);
1884 for (std::map<const char *, d3::pt>::iterator i = d3_depth_pt.begin();
1885 i != d3_depth_pt.end(); i++) {
1887 const d2::image *im = d3::scene::depth(i->second);
1888 d2::image_rw::write_image(i->first, im, output_exposure, 1, 1);
1889 delete im;
1892 fprintf(stderr, ".\n");
1894 for (unsigned int i = d2::image_rw::count(); i < d3_count; i++) {
1895 if (d3_depth[i] != NULL) {
1896 fprintf(stderr, "\n\n*** Frame number for --3dd too high. ***\n\n");
1898 if (d3_output[i] != NULL) {
1899 fprintf(stderr, "\n\n*** Frame number for --3dv too high. ***\n\n");
1905 * Destroy the image file handler
1908 d2::image_rw::destroy();
1911 * Delete the transformation file structures, if any
1912 * exist.
1915 tsave_delete(tsave);
1916 tload_delete(tload);
1919 * We're done.
1922 exit(0);
1927 * If there was no output, the user might need more information.
1930 hi.usage();
1931 exit(1);