Add mechanism to check validity of stored environment pointers in ui::input::environment.
[Ale.git] / ui / input.h
blob037e33c466cb944f954f28abbfa91efdfa4d85a6
1 // Copyright 2002, 2003, 2004, 2005, 2006 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 * ANSI C and POSIX include files.
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <time.h>
30 #include <math.h>
31 #include <stack>
32 #include <map>
35 * Types
38 #include "../ale_pos.h"
39 #include "../ale_real.h"
42 * Interface files
45 #include "ui.h"
46 #include "unsupported.h"
47 #include "implication.h"
50 * 2D include files
53 #include "../d2.h"
56 * 3D include files
59 #include "../d3.h"
62 * Device configuration files
65 #include "../device/xvp610_320x240.h"
66 #include "../device/xvp610_640x480.h"
67 #include "../device/ov7620_raw_linear.h"
68 #include "../device/canon_300d_raw_linear.h"
69 #include "../device/canon_300d_raw_linear_85mm_1_8.h"
70 #include "../device/canon_300d_raw_linear_50mm_1_8.h"
71 #include "../device/canon_300d_raw_linear_50mm_1_4.h"
72 #include "../device/canon_300d_raw_linear_50mm_1_4_1_4.h"
75 * Help files
78 #include "help.h"
81 * Argument counter.
83 * Counts instances of a given option.
85 unsigned int arg_count(int argc, const char *argv[], const char *arg) {
86 unsigned int count = 0;
87 for (int i = 0; i < argc; i++) {
88 if (!strcmp(argv[i], arg))
89 count++;
90 else if (!strcmp(argv[i], "--"))
91 return count;
93 return count;
97 * Argument prefix counter.
99 * Counts instances of a given option prefix.
101 unsigned int arg_prefix_count(int argc, const char *argv[], const char *pfix) {
102 unsigned int count = 0;
103 for (int i = 0; i < argc; i++) {
104 if (!strncmp(argv[i], pfix, strlen(pfix)))
105 count++;
106 else if (!strcmp(argv[i], "--"))
107 return count;
109 return count;
113 * Reallocation function
115 void *local_realloc(void *ptr, size_t size) {
116 void *new_ptr = realloc(ptr, size);
118 if (new_ptr == NULL)
119 ui::get()->memory_error_location("main()");
121 return new_ptr;
125 * Not enough arguments function.
127 void not_enough(const char *opt_name) {
128 ui::get()->cli_not_enough(opt_name);
132 * Bad argument function
134 void bad_arg(const char *opt_name) {
135 ui::get()->cli_bad_arg(opt_name);
138 class input {
140 * Environment structures.
142 * XXX: It's arguable that these should be public members of the
143 * 'input' class in order to allow passing environment values to other
144 * classes, but, since we're currently using them only to prepare state
145 * for an internal 'input' function, they can stay private for now. A
146 * more nuanced approach will likely be required later.
149 class environment {
150 static std::stack<environment *> environment_stack;
151 static std::set<environment *> environment_set;
153 std::map<const char *, const char *> environment_map;
155 public:
156 const char *get(const char *name) {
157 if (environment_map.count(name) == 0)
158 return NULL;
160 return environment_map[name];
163 void set(const char *name, const char *value) {
164 environment_map[name] = value;
167 void set_ptr(const char *name, const void *pointer) {
168 int chars = sizeof(void *) * 2 + 3;
169 char *c = (char *) malloc(sizeof(char) * chars);
171 assert(c);
173 if (!c)
174 ui::get()->memory_error_location("environment::set_ptr");
176 int count = snprintf(c, chars, "%p", pointer);
178 assert (count >= 0 && count < chars);
180 set(name, c);
184 * Make an environment substructure. Note that since deep
185 * structures are currently referenced rather than copied when
186 * the stack is pushed, there is no current need for any
187 * chaining mechanism.
189 void make_substructure(const char *name) {
190 environment *s = new environment;
191 set_ptr(name, s);
192 environment_set.insert(s);
196 static environment *get_env(const char *name) {
197 void *ptr_value;
198 sscanf(name, "%p", &ptr_value);
201 * Check for bad pointers.
204 if (!environment_set.count((environment *) ptr_value)) {
205 assert(0);
206 fprintf(stderr, "Bad environment pointer.\n");
207 exit(1);
210 return (environment *) ptr_value;
213 static environment *top() {
214 if (environment_stack.empty()) {
215 environment_stack.push(new environment);
216 environment_set.insert(environment_stack.top());
218 return environment_stack.top();
221 static void push() {
222 environment *e = new environment;
224 e->environment_map = environment_stack.top()->environment_map;
226 e->set_ptr("---chain", environment_stack.top());
228 environment_stack.push(e);
229 environment_set.insert(e);
232 static void pop() {
233 assert(!environment_stack.empty());
236 * Execution environments should never be referenced by
237 * structures further up the call chain, so they can
238 * safely be deleted. (XXX: In particular, while
239 * lexical scoping may require copying of execution
240 * environments from lower on the call chain, there is
241 * no obvious reason that a reference should be used in
242 * this case; a shallow copy should be used instead.)
245 environment_set.erase(environment_stack.top());
246 delete environment_stack.top();
248 environment_stack.pop();
253 * Read tokens from a stream.
255 class token_reader {
257 * Get the next token
259 virtual char *get() = 0;
261 virtual ~token_reader() {
265 class cli_token_reader {
267 int arg_index;
268 int argc;
269 const char **argv;
271 cli_token_reader(int c, const char *v[]) {
272 argc = c;
273 argv = v;
274 arg_index = 1;
277 const char *get() {
278 return argv[arg_index++];
282 public:
284 * Input handler.
286 * Does one of two things:
288 * (1) Output version information if called with '--version'
290 * (2) Read options and file arguments, and if the arguments are correct,
291 * write output. If an error is detected, print the usage statement.
295 static void handle(int argc, const char *argv[], const char *package, const char *short_version, const char *version) {
298 * Initialize help object
301 help hi(package, argv[0], short_version);
304 * Output version information if --version appears
305 * on the command line.
308 if (arg_count(argc, argv, "--version")) {
310 * Output the version
313 fprintf(stdout, "%s", version);
315 return;
319 * Handle help options
322 if (arg_prefix_count(argc, argv, "--h"))
323 for (int i = 1; i < argc; i++) {
324 int all = !strcmp(argv[i], "--hA");
325 int is_help_option = !strncmp(argv[i], "--h", strlen("--h"));
326 int found_help = 0;
328 if (!strcmp(argv[i], "--hu") || all)
329 hi.usage(), found_help = 1;
330 if (!strcmp(argv[i], "--hq") || all)
331 hi.defaults(), found_help = 1;
332 if (!strcmp(argv[i], "--hf") || all)
333 hi.file(), found_help = 1;
334 if (!strcmp(argv[i], "--he") || all)
335 hi.exclusion(), found_help = 1;
336 if (!strcmp(argv[i], "--ha") || all)
337 hi.alignment(), found_help = 1;
338 if (!strcmp(argv[i], "--hr") || all)
339 hi.rendering(), found_help = 1;
340 if (!strcmp(argv[i], "--hx") || all)
341 hi.exposure(), found_help = 1;
342 if (!strcmp(argv[i], "--ht") || all)
343 hi.tdf(), found_help = 1;
344 if (!strcmp(argv[i], "--hl") || all)
345 hi.filtering(), found_help = 1;
346 if (!strcmp(argv[i], "--hd") || all)
347 hi.device(), found_help = 1;
348 if (!strcmp(argv[i], "--hi") || all)
349 hi.interface(), found_help = 1;
350 if (!strcmp(argv[i], "--hv") || all)
351 hi.visp(), found_help = 1;
352 if (!strcmp(argv[i], "--hc") || all)
353 hi.cp(), found_help = 1;
354 if (!strcmp(argv[i], "--h3") || all)
355 hi.d3(), found_help = 1;
356 if (!strcmp(argv[i], "--hz") || all)
357 hi.undocumented(), found_help = 1;
359 if (is_help_option && !found_help)
360 hi.usage();
363 * Check for the end-of-options marker, a non-option argument,
364 * or the end of arguments. In all of these cases, we exit.
367 if (!strcmp(argv[i], "--")
368 || strncmp(argv[i], "--", strlen("--"))
369 || i == argc - 1)
370 return;
374 * Undocumented projective transformation utility
377 if (arg_count(argc, argv, "--ptcalc") > 0) {
378 fprintf(stderr, "\n\n*** Warning: this feature is not documented ***\n\n");
379 printf("Enter: w h tlx tly blx bly brx bry trx try x y\n\n");
381 double w, h, tlx, tly, blx, bly, brx, bry, trx, tr_y, x, y;
383 printf("> ");
385 if (scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",
386 &w, &h, &tlx, &tly, &blx, &bly, &brx, &bry, &trx, &tr_y, &x, &y) != 12) {
388 fprintf(stderr, "Error reading input.\n");
389 exit(1);
392 d2::image *i = new d2::image_ale_real((int)h, (int)w, 3);
393 d2::transformation t = d2::transformation::gpt_identity(i, 1);
394 d2::point q[4] = {
395 d2::point(tly, tlx),
396 d2::point(bly, blx),
397 d2::point(bry, brx),
398 d2::point(tr_y, trx)
400 t.gpt_set(q);
402 d2::point a(y, x), b;
404 b = t.transform_scaled(a);
406 printf("TRANSFORM t(a): (%f, %f)\n", (double) b[1], (double) b[0]);
408 b = t.scaled_inverse_transform(a);
410 printf("INVERSE t^-1(a): (%f, %f)\n", (double) b[1], (double) b[0]);
412 exit(0);
416 * Flags and variables
419 double scale_factor = 1;
420 double vise_scale_factor = 1;
421 #if 0
422 double usm_multiplier = 0.0;
423 #endif
424 int extend = 0;
425 struct d2::tload_t *tload = NULL;
426 struct d2::tsave_t *tsave = NULL;
427 struct d3::tload_t *d3_tload = NULL;
428 struct d3::tsave_t *d3_tsave = NULL;
429 int ip_iterations = 0;
430 int ip_use_median = 0;
431 enum { psf_linear, psf_nonlinear, psf_N };
432 const char *psf[psf_N] = {NULL, NULL};
433 const char *device = NULL;
434 int psf_match = 0;
435 double psf_match_args[6];
436 int inc = 1;
437 int exposure_register = 1;
438 const char *wm_filename = NULL;
439 int wm_offsetx, wm_offsety;
440 double cx_parameter = 0;
441 double *d3px_parameters = NULL;
442 int d3px_count = 0;
443 int *ex_parameters = NULL;
444 int ex_count = 0;
445 int ex_show = 0;
446 d2::render *achain;
447 const char *achain_type = "triangle:2";
448 const char *afilter_type = "internal";
449 d2::render **ochain = NULL;
450 const char **ochain_names = NULL;
451 const char **ochain_types = NULL;
452 const char *d3chain_type = NULL;
453 int oc_count = 0;
454 const char **visp = NULL;
455 int vise_count = 0;
456 const char **d3_output = NULL;
457 const char **d3_depth = NULL;
458 unsigned int d3_count = 0;
459 double user_view_angle = 0;
460 int user_bayer = IMAGE_BAYER_DEFAULT;
461 d2::pixel exp_mult = d2::pixel(1, 1, 1);
462 std::map<const char *, d3::pt> d3_output_pt;
463 std::map<const char *, d3::pt> d3_depth_pt;
466 * dchain is ochain[0].
469 ochain = (d2::render **) local_realloc(ochain,
470 (oc_count + 1) * sizeof(d2::render *));
471 ochain_names = (const char **) local_realloc((void *)ochain_names,
472 (oc_count + 1) * sizeof(const char *));
473 ochain_types = (const char **) local_realloc((void *)ochain_types,
474 (oc_count + 1) * sizeof(const char *));
476 ochain_types[0] = "sinc*lanc:8";
478 oc_count = 1;
481 * Handle default settings
484 if (arg_prefix_count(argc, argv, "--q") > 1)
485 ui::get()->error("more than one default setting option --q* was specified");
487 if (arg_count(argc, argv, "--q0")) {
488 ochain_types[0] = "fine:box:1,triangle:2";
489 achain_type = "triangle:2";
490 d2::align::mc(0.3);
491 ip_iterations = 0;
492 d2::image_rw::exp_noscale();
493 cx_parameter = 0;
494 } else if (arg_count(argc, argv, "--qn")) {
495 ochain_types[0] = "sinc*lanc:6";
496 achain_type = "sinc*lanc:6";
497 d2::align::mc(0.5);
498 ip_iterations = 0;
499 d2::image_rw::exp_noscale();
500 cx_parameter = 0;
501 } else if (arg_count(argc, argv, "--q1")) {
502 ochain_types[0] = "median:fine:sinc*lanc:8,triangle:2";
503 achain_type = "triangle:2";
504 d2::align::mc(0.5);
505 ip_iterations = 0;
506 d2::image_rw::exp_noscale();
507 cx_parameter = 0;
508 } else if (arg_count(argc, argv, "--q2")) {
509 ochain_types[0] = "sinc*lanc:8";
510 achain_type = "sinc*lanc:8";
511 d2::align::no_mc();
512 ip_iterations = 4;
513 d2::image_rw::exp_noscale();
514 cx_parameter = 0;
515 } else if (arg_count(argc, argv, "--qr")) {
516 ochain_types[0] = "sinc*lanc:8";
517 achain_type = "sinc*lanc:8";
518 d2::align::no_mc();
519 ip_iterations = 6;
520 d2::image_rw::exp_scale();
521 cx_parameter = 0.7;
522 } else {
524 * Same as --q0
526 ochain_types[0] = "fine:box:1,triangle:2";
527 achain_type = "triangle:2";
528 d2::align::mc(0.3);
529 ip_iterations = 0;
530 d2::image_rw::exp_noscale();
531 cx_parameter = 0;
535 * Set default d3chain to default ochain[0].
538 d3chain_type = ochain_types[0];
541 * Iterate through arguments until we reach the first file
542 * argument. After the first file argument, we assume that
543 * all following arguments are files.
546 for (int i = 1; i < argc - 1; i++) {
549 if (!strcmp(argv[i], "--q0")
550 || !strcmp(argv[i], "--q1")
551 || !strcmp(argv[i], "--q2")
552 || !strcmp(argv[i], "--qr")
553 || !strcmp(argv[i], "--qn")) {
555 * Do nothing. Defaults have already been set.
557 } else if (!strcmp(argv[i], "--8bpc")) {
558 d2::image_rw::depth8();
559 } else if (!strcmp(argv[i], "--16bpc")) {
560 d2::image_rw::depth16();
561 } else if (!strcmp(argv[i], "--plain")) {
562 d2::image_rw::ppm_plain();
563 } else if (!strcmp(argv[i], "--raw")) {
564 d2::image_rw::ppm_raw();
565 } else if (!strcmp(argv[i], "--auto")) {
566 d2::image_rw::ppm_auto();
567 } else if (!strcmp(argv[i], "--align-all")) {
568 d2::align::all();
569 } else if (!strcmp(argv[i], "--align-green")) {
570 d2::align::green();
571 } else if (!strcmp(argv[i], "--align-sum")) {
572 d2::align::sum();
573 } else if (!strcmp(argv[i], "--translation")) {
574 d2::align::class_translation();
575 } else if (!strcmp(argv[i], "--euclidean")) {
576 d2::align::class_euclidean();
577 } else if (!strcmp(argv[i], "--projective")) {
578 d2::align::class_projective();
579 } else if (!strcmp(argv[i], "--identity")) {
580 d2::align::initial_default_identity();
581 } else if (!strcmp(argv[i], "--follow")) {
582 d2::align::initial_default_follow();
583 } else if (!strcmp(argv[i], "--perturb-output")) {
584 d2::align::perturb_output();
585 } else if (!strcmp(argv[i], "--perturb-source")) {
586 d2::align::perturb_source();
587 } else if (!strcmp(argv[i], "--fail-optimal")) {
588 d2::align::fail_optimal();
589 } else if (!strcmp(argv[i], "--fail-default")) {
590 d2::align::fail_default();
591 } else if (!strcmp(argv[i], "--no-extend")) {
592 extend = 0;
593 } else if (!strcmp(argv[i], "--extend")) {
594 extend = 1;
595 } else if (!strcmp(argv[i], "--no-mc")) {
596 d2::align::no_mc();
597 } else if (!strcmp(argv[i], "--oc")) {
598 d3::scene::oc();
599 } else if (!strcmp(argv[i], "--no-oc")) {
600 d3::scene::no_oc();
601 } else if (!strcmp(argv[i], "--gs")) {
602 if (i + 1 >= argc)
603 not_enough("--gs");
605 d2::align::gs(argv[i+1]);
606 i += 1;
608 } else if (!strcmp(argv[i], "--gs-mo")) {
609 if (i + 1 >= argc)
610 not_enough("--gs-mo");
612 unsigned int mo_parameter;
613 if (sscanf(argv[i+1], "%u", &mo_parameter) != 1)
614 bad_arg("--gs-mo");
616 d2::align::gs_mo(mo_parameter);
617 i += 1;
619 } else if (!strcmp(argv[i], "--focus")) {
622 * Check for argument availability
625 if (i + 1 >= argc)
626 not_enough(argv[i]);
628 double one = +1;
629 double zero = +0;
630 double inf = one / zero;
632 assert (isinf(inf) == +1);
635 * Focus type
638 unsigned int type = 0;
639 double distance;
640 double px, py;
642 if (!strcmp(argv[i+1], "d")) {
644 type = 0;
646 if (i + 2 > argc)
647 not_enough("--focus d");
649 if (sscanf(argv[i+2], "%lf", &distance) != 1)
650 bad_arg("--focus d");
652 i += 2;
654 } else if (!strcmp(argv[i+1], "p")) {
656 type = 1;
658 if (i + 3 > argc)
659 not_enough("--focus");
661 if (sscanf(argv[i+2], "%lf", &px) != 1
662 || sscanf(argv[i+3], "%lf", &py) != 1)
663 bad_arg("--focus");
665 i += 3;
667 } else {
668 bad_arg(argv[i]);
672 * Options
675 unsigned int ci = 0;
676 double fr = 0;
677 double ht = 0;
678 double vt = 0;
679 double sd = 0;
680 double ed = inf;
681 double sx = -inf;
682 double ex = inf;
683 double sy = -inf;
684 double ey = inf;
685 double ap = 3;
686 unsigned int sc = 3;
687 unsigned int fs = 0;
688 unsigned int sr = 0;
690 int options = 1;
692 i++;
694 while (options && i < argc) {
695 if (!strncmp(argv[i], "ci=", 3)) {
696 if(sscanf(argv[i] + 3, "%u", &ci) != 1)
697 bad_arg("--focus");
698 } else if (!strncmp(argv[i], "fr=", 3)) {
699 if(sscanf(argv[i] + 3, "%lf", &fr) != 1)
700 bad_arg("--focus");
701 } else if (!strncmp(argv[i], "ht=", 3)) {
702 if(sscanf(argv[i] + 3, "%lf", &ht) != 1)
703 bad_arg("--focus");
704 } else if (!strncmp(argv[i], "vt=", 3)) {
705 if(sscanf(argv[i] + 3, "%lf", &vt) != 1)
706 bad_arg("--focus");
707 } else if (!strncmp(argv[i], "sy=", 3)) {
708 if(sscanf(argv[i] + 3, "%lf", &sy) != 1)
709 bad_arg("--focus");
710 } else if (!strncmp(argv[i], "ey=", 3)) {
711 if(sscanf(argv[i] + 3, "%lf", &ey) != 1)
712 bad_arg("--focus");
713 } else if (!strncmp(argv[i], "sx=", 3)) {
714 if(sscanf(argv[i] + 3, "%lf", &sx) != 1)
715 bad_arg("--focus");
716 } else if (!strncmp(argv[i], "ex=", 3)) {
717 if(sscanf(argv[i] + 3, "%lf", &ex) != 1)
718 bad_arg("--focus");
719 } else if (!strncmp(argv[i], "sd=", 3)) {
720 if(sscanf(argv[i] + 3, "%lf", &sd) != 1)
721 bad_arg("--focus");
722 } else if (!strncmp(argv[i], "ed=", 3)) {
723 if(sscanf(argv[i] + 3, "%lf", &ed) != 1)
724 bad_arg("--focus");
725 } else if (!strncmp(argv[i], "ap=", 3)) {
726 if(sscanf(argv[i] + 3, "%lf", &ap) != 1)
727 bad_arg("--focus");
728 } else if (!strncmp(argv[i], "sc=", 3)) {
729 if(sscanf(argv[i] + 3, "%u", &sc) != 1)
730 bad_arg("--focus");
731 } else if (!strncmp(argv[i], "sr=", 3)) {
732 if (!strcmp(argv[i], "sr=aperture")) {
733 sr = 0;
734 } else if (!strcmp(argv[i], "sr=pixel")) {
735 sr = 1;
736 } else
737 bad_arg("--focus");
739 } else if (!strncmp(argv[i], "fs=", 3)) {
740 if (!strcmp(argv[i], "fs=mean")) {
741 fs = 0;
742 } else if (!strcmp(argv[i], "fs=median")) {
743 fs = 1;
744 } else
745 bad_arg("--focus");
746 } else
747 options = 0;
749 if (options)
750 i++;
753 i--;
755 d3::focus::add_region(type, distance, px, py, ci, fr, ht, vt, sd, ed, sx, ex, sy, ey, ap, sc, fs, sr);
757 } else if (!strcmp(argv[i], "--3ddp") || !strcmp(argv[i], "--3dvp")) {
758 d2::align::keep();
761 * Unsupported configurations
764 if (ip_iterations)
765 unsupported::fornow("3D modeling with Irani-Peleg rendering");
767 #if 0
768 if (usm_multiplier)
769 unsupported::fornow("3D modeling with unsharp mask");
770 #endif
773 * Check for argument availability
776 if (i + 10 >= argc)
777 not_enough(argv[i]);
780 * Initialize if necessary
782 * Note: because their existence is checked as an
783 * indicator of the presence of 3D arguments, we
784 * initialize these structures here.
787 if (d3_output == NULL) {
788 d3_count = argc - (i + 2) - 1;
789 d3_output = (const char **) calloc(d3_count, sizeof(char *));
790 d3_depth = (const char **) calloc(d3_count, sizeof(char *));
793 unsigned int width, height;
794 double view_angle;
795 double x, y, z;
796 double P, Y, R;
798 if (sscanf(argv[i+1], "%u", &width) != 1
799 || sscanf(argv[i+2], "%u", &height) != 1
800 || sscanf(argv[i+3], "%lf", &view_angle) != 1
801 || sscanf(argv[i+4], "%lf", &x) != 1
802 || sscanf(argv[i+5], "%lf", &y) != 1
803 || sscanf(argv[i+6], "%lf", &z) != 1
804 || sscanf(argv[i+7], "%lf", &P) != 1
805 || sscanf(argv[i+8], "%lf", &Y) != 1
806 || sscanf(argv[i+9], "%lf", &R) != 1)
807 bad_arg(argv[i]);
809 view_angle *= M_PI / 180;
810 P *= M_PI / 180;
811 Y *= M_PI / 180;
812 R *= M_PI / 180;
814 d2::transformation t =
815 d2::transformation::eu_identity();
816 t.set_domain(height, width);
817 d3::pt _pt(t, d3::et(y, x, z, Y, P, R), view_angle);
819 if (!strcmp(argv[i], "--3dvp")) {
820 d3_output_pt[argv[i+10]] = _pt;
821 } else if (!strcmp(argv[i], "--3ddp")) {
822 d3_depth_pt[argv[i+10]] = _pt;
823 } else {
824 assert(0);
827 i+=10;
828 } else if (!strcmp(argv[i], "--3dv")) {
829 d2::align::keep();
831 unsigned int frame_no;
834 * Unsupported configurations
837 if (ip_iterations)
838 unsupported::fornow("3D modeling with Irani-Peleg rendering");
840 #if 0
841 if (usm_multiplier)
842 unsupported::fornow("3D modeling with unsharp mask");
843 #endif
846 * Check for argument availability
849 if (i + 2 >= argc)
850 not_enough("--3dv");
853 * Initialize if necessary
856 if (d3_output == NULL) {
857 d3_count = argc - (i + 2) - 1;
858 d3_output = (const char **) calloc(d3_count, sizeof(char *));
859 d3_depth = (const char **) calloc(d3_count, sizeof(char *));
862 if (sscanf(argv[i+1], "%d", &frame_no) != 1)
863 ui::get()->error("--3dv argument 0 must be an integer");
865 if (frame_no >= d3_count)
866 ui::get()->error("--3dv argument 0 is too large");
868 if (d3_output[frame_no] != NULL) {
869 unsupported::fornow ("Writing a single 3D view to more than one output file");
872 d3_output[frame_no] = argv[i+2];
874 i+=2;
875 } else if (!strcmp(argv[i], "--3dd")) {
876 d2::align::keep();
878 unsigned int frame_no;
881 * Unsupported configurations
884 if (ip_iterations)
885 unsupported::fornow("3D modeling with Irani-Peleg rendering");
887 #if 0
888 if (usm_multiplier)
889 unsupported::fornow("3D modeling with unsharp mask");
890 #endif
893 * Check for argument availability
896 if (i + 2 >= argc)
897 not_enough("--3dd");
900 * Initialize if necessary
903 if (d3_output == NULL) {
904 d3_count = argc - (i + 2) - 1;
905 d3_output = (const char **) calloc(d3_count, sizeof(char *));
906 d3_depth = (const char **) calloc(d3_count, sizeof(char *));
909 if (sscanf(argv[i+1], "%d", &frame_no) != 1)
910 ui::get()->error("--3dd argument 0 must be an integer");
912 if (frame_no >= d3_count)
913 ui::get()->error("--3dd argument 0 is too large");
915 if (d3_depth[frame_no] != NULL) {
916 unsupported::fornow ("Writing a single frame's depth info to more than one output file");
919 d3_depth[frame_no] = argv[i+2];
921 i+=2;
923 } else if (!strcmp(argv[i], "--view-angle")) {
924 if (i + 1 >= argc)
925 not_enough("--view-angle");
927 double va_parameter;
928 sscanf(argv[i+1], "%lf", &va_parameter);
929 i += 1;
930 user_view_angle = va_parameter * M_PI / 180;
931 } else if (!strcmp(argv[i], "--cpf-load")) {
932 if (i + 1 >= argc)
933 not_enough("--cpf-load");
935 d3::cpf::init_loadfile(argv[i+1]);
936 i += 1;
937 } else if (!strcmp(argv[i], "--ui=stream")) {
938 ui::set_stream();
939 } else if (!strcmp(argv[i], "--ui=tty")) {
940 ui::set_tty();
941 } else if (!strcmp(argv[i], "--3d-fmr")) {
943 if (i + 1 >= argc)
944 not_enough("--3d-fmr");
946 double fmr_parameter;
947 sscanf(argv[i+1], "%lf", &fmr_parameter);
948 i += 1;
949 d3::scene::fmr(fmr_parameter);
951 } else if (!strcmp(argv[i], "--3d-dmr")) {
953 if (i + 1 >= argc)
954 not_enough("--3d-dmr");
956 double dmr_parameter;
957 sscanf(argv[i+1], "%lf", &dmr_parameter);
958 i += 1;
959 d3::scene::dmr(dmr_parameter);
961 } else if (!strcmp(argv[i], "--et")) {
963 if (i + 1 >= argc)
964 not_enough("--et");
966 double et_parameter;
967 sscanf(argv[i+1], "%lf", &et_parameter);
968 i += 1;
969 d3::scene::et(et_parameter);
971 } else if (!strcmp(argv[i], "--st")) {
972 if (i + 1 >= argc)
973 not_enough("--st");
975 double st_parameter;
976 sscanf(argv[i+1], "%lf", &st_parameter);
977 i += 1;
978 d3::cpf::st(st_parameter);
979 } else if (!strcmp(argv[i], "--di-lower")) {
980 if (i + 1 >= argc)
981 not_enough("--di-lower");
983 double di_parameter;
984 sscanf(argv[i+1], "%lf", &di_parameter);
985 i += 1;
986 d3::scene::di_lower(di_parameter);
987 } else if (!strcmp(argv[i], "--rc")) {
988 if (i + 1 >= argc)
989 not_enough("--rc");
991 double rc_parameter;
992 sscanf(argv[i+1], "%lf", &rc_parameter);
993 i += 1;
994 d3::scene::rc(rc_parameter);
995 } else if (!strcmp(argv[i], "--do-try")) {
996 if (i + 1 >= argc)
997 not_enough("--do-try");
999 double do_parameter;
1000 sscanf(argv[i+1], "%lf", &do_parameter);
1001 i += 1;
1002 d3::scene::do_try(do_parameter);
1003 } else if (!strcmp(argv[i], "--di-upper")) {
1004 if (i + 1 >= argc)
1005 not_enough("--di-upper");
1007 double dgi_parameter;
1008 sscanf(argv[i+1], "%lf", &dgi_parameter);
1009 i += 1;
1010 d3::scene::di_upper(dgi_parameter);
1011 } else if (!strcmp(argv[i], "--fc")) {
1012 if (i + 1 >= argc)
1013 not_enough("--fc");
1015 double fc_parameter;
1016 sscanf(argv[i+1], "%lf", &fc_parameter);
1017 i += 1;
1018 d3::scene::fc(fc_parameter);
1019 } else if (!strcmp(argv[i], "--ecm")) {
1020 unsupported::discontinued("--ecm <x>");
1021 } else if (!strcmp(argv[i], "--acm")) {
1022 unsupported::discontinued("--acm <x>");
1023 } else if (!strcmp(argv[i], "--def-nn")) {
1024 if (i + 1 >= argc)
1025 not_enough("--def-nn");
1027 double nn_parameter;
1028 sscanf(argv[i+1], "%lf", &nn_parameter);
1029 i += 1;
1030 d2::image_rw::def_nn(nn_parameter);
1032 if (nn_parameter > 2) {
1033 fprintf(stderr, "\n\n*** Warning: --def-nn implementation is currently "
1034 "inefficient for large radii. ***\n\n");
1037 } else if (!strcmp(argv[i], "--mc")) {
1038 if (i + 1 >= argc)
1039 not_enough("--mc");
1041 double mc_parameter;
1042 sscanf(argv[i+1], "%lf", &mc_parameter);
1043 mc_parameter /= 100;
1044 i += 1;
1045 d2::align::mc(mc_parameter);
1047 } else if (!strcmp(argv[i], "--fx")) {
1049 if (i + 1 >= argc)
1050 not_enough("--fx");
1052 double fx_parameter;
1053 sscanf(argv[i+1], "%lf", &fx_parameter);
1054 i += 1;
1055 d3::scene::fx(fx_parameter);
1057 } else if (!strcmp(argv[i], "--tcem")) {
1059 if (i + 1 >= argc)
1060 not_enough("--tcem");
1062 double tcem_parameter;
1063 sscanf(argv[i+1], "%lf", &tcem_parameter);
1064 i += 1;
1065 d3::scene::tcem(tcem_parameter);
1067 } else if (!strcmp(argv[i], "--oui")) {
1069 if (i + 1 >= argc)
1070 not_enough("--oui");
1072 unsigned int oui_parameter;
1073 sscanf(argv[i+1], "%u", &oui_parameter);
1074 i += 1;
1075 d3::scene::oui(oui_parameter);
1077 } else if (!strcmp(argv[i], "--pa")) {
1079 if (i + 1 >= argc)
1080 not_enough("--pa");
1082 unsigned int pa_parameter;
1083 sscanf(argv[i+1], "%u", &pa_parameter);
1084 i += 1;
1085 d3::scene::pa(pa_parameter);
1087 } else if (!strcmp(argv[i], "--pc")) {
1089 if (i + 1 >= argc)
1090 not_enough("--pc");
1092 d3::scene::pc(argv[i+1]);
1093 i += 1;
1095 } else if (!strcmp(argv[i], "--cw")) {
1096 d2::align::certainty_weighted(1);
1097 } else if (!strcmp(argv[i], "--no-cw")) {
1098 d2::align::certainty_weighted(0);
1099 } else if (!strcmp(argv[i], "--wm")) {
1100 if (wm_filename != NULL)
1101 ui::get()->error("only one weight map can be specified");
1103 if (i + 3 >= argc)
1104 not_enough("--wm");
1105 wm_filename = argv[i+1];
1107 if (sscanf(argv[i+2], "%d", &wm_offsetx) != 1)
1108 ui::get()->error("--wm x-argument must be an integer");
1110 if (sscanf(argv[i+3], "%d", &wm_offsety) != 1)
1111 ui::get()->error("--wm y-argument must be an integer");
1113 i += 3;
1115 } else if (!strcmp(argv[i], "--fl")) {
1116 if (i + 3 >= argc)
1117 not_enough("--fl");
1118 double h, v, a;
1119 if (sscanf(argv[i+1], "%lf", &h) != 1)
1120 ui::get()->error("--fl h-argument must be numerical");
1121 if (sscanf(argv[i+2], "%lf", &v) != 1)
1122 ui::get()->error("--fl v-argument must be numerical");
1123 if (sscanf(argv[i+3], "%lf", &a) != 1)
1124 ui::get()->error("--fl a-argument must be numerical");
1125 i += 3;
1126 #ifdef USE_FFTW
1127 d2::align::set_frequency_cut(h, v, a);
1128 #else
1129 ui::get()->error_hint("--fl is not supported", "rebuild ALE with FFTW=1");
1130 #endif
1131 } else if (!strcmp(argv[i], "--wmx")) {
1132 if (i + 3 >= argc)
1133 not_enough("--wmx");
1134 #ifdef USE_UNIX
1135 d2::align::set_wmx(argv[i+1], argv[i+2], argv[i+3]);
1136 #else
1137 ui::get()->error_hint("--wmx is not supported", "rebuild ALE with POSIX=1");
1138 #endif
1139 i += 3;
1140 } else if (!strcmp(argv[i], "--flshow")) {
1141 if (i + 1 >= argc)
1142 not_enough("--flshow");
1143 d2::align::set_fl_show(argv[i+1]);
1144 i++;
1145 } else if (!strcmp(argv[i], "--3dpx")) {
1146 if (i + 6 >= argc)
1147 not_enough("--3dpx");
1149 d3px_parameters = (double *) local_realloc(d3px_parameters, (d3px_count + 1) * 6 * sizeof(double));
1151 for (int param = 0; param < 6; param++)
1152 if (sscanf(argv[i + param + 1], "%lf", &(d3px_parameters[6 * d3px_count + param])) != 1)
1153 bad_arg("--d3px");
1156 * Swap x and y, since their internal meanings differ from their external meanings.
1159 for (int param = 0; param < 2; param++) {
1160 double temp = d3px_parameters[6 * d3px_count + 2 + param];
1161 d3px_parameters[6 * d3px_count + 2 + param] = d3px_parameters[6 * d3px_count + 0 + param];
1162 d3px_parameters[6 * d3px_count + 0 + param] = temp;
1167 * Increment counters
1170 d3px_count++;
1171 i += 6;
1172 } else if (!strcmp(argv[i], "--ex")) {
1173 if (i + 6 >= argc)
1174 not_enough("--ex");
1176 ex_parameters = (int *) local_realloc(ex_parameters, (ex_count + 1) * 6 * sizeof(int));
1178 for (int param = 0; param < 6; param++)
1179 if (sscanf(argv[i + param + 1], "%d", &(ex_parameters[6 * ex_count + param])) != 1)
1180 bad_arg("--ex");
1183 * Swap x and y, since their internal meanings differ from their external meanings.
1186 for (int param = 0; param < 2; param++) {
1187 int temp = ex_parameters[6 * ex_count + 2 + param];
1188 ex_parameters[6 * ex_count + 2 + param] = ex_parameters[6 * ex_count + 0 + param];
1189 ex_parameters[6 * ex_count + 0 + param] = temp;
1194 * Increment counters
1197 ex_count++;
1198 i += 6;
1199 } else if (!strcmp(argv[i], "--crop")) {
1200 if (i + 6 >= argc)
1201 not_enough("--crop");
1203 ex_parameters = (int *) local_realloc(ex_parameters, (ex_count + 4) * 6 * sizeof(int));
1204 int crop_args[6];
1206 for (int param = 0; param < 6; param++)
1207 if (sscanf(argv[i + param + 1], "%d", &(crop_args[param])) != 1)
1208 bad_arg("--crop");
1211 * Construct exclusion regions from the crop area,
1212 * swapping x and y, since their internal meanings
1213 * differ from their external meanings.
1217 * Exclusion region 1: low x
1220 ex_parameters[6 * ex_count + 0] = INT_MIN;
1221 ex_parameters[6 * ex_count + 1] = crop_args[2] - 1;
1222 ex_parameters[6 * ex_count + 2] = INT_MIN;
1223 ex_parameters[6 * ex_count + 3] = INT_MAX;
1224 ex_parameters[6 * ex_count + 4] = crop_args[4];
1225 ex_parameters[6 * ex_count + 5] = crop_args[5];
1228 * Exclusion region 2: low y
1231 ex_parameters[6 * ex_count + 6] = INT_MIN;
1232 ex_parameters[6 * ex_count + 7] = INT_MAX;
1233 ex_parameters[6 * ex_count + 8] = INT_MIN;
1234 ex_parameters[6 * ex_count + 9] = crop_args[0] - 1;
1235 ex_parameters[6 * ex_count + 10] = crop_args[4];
1236 ex_parameters[6 * ex_count + 11] = crop_args[5];
1239 * Exclusion region 3: high y
1242 ex_parameters[6 * ex_count + 12] = INT_MIN;
1243 ex_parameters[6 * ex_count + 13] = INT_MAX;
1244 ex_parameters[6 * ex_count + 14] = crop_args[1] + 1;
1245 ex_parameters[6 * ex_count + 15] = INT_MAX;
1246 ex_parameters[6 * ex_count + 16] = crop_args[4];
1247 ex_parameters[6 * ex_count + 17] = crop_args[5];
1250 * Exclusion region 4: high x
1253 ex_parameters[6 * ex_count + 18] = crop_args[3] + 1;
1254 ex_parameters[6 * ex_count + 19] = INT_MAX;
1255 ex_parameters[6 * ex_count + 20] = INT_MIN;
1256 ex_parameters[6 * ex_count + 21] = INT_MAX;
1257 ex_parameters[6 * ex_count + 22] = crop_args[4];
1258 ex_parameters[6 * ex_count + 23] = crop_args[5];
1261 * Increment counters
1264 ex_count += 4;
1265 i += 6;
1266 } else if (!strcmp(argv[i], "--exshow")) {
1267 ex_show = 1;
1268 } else if (!strcmp(argv[i], "--wt")) {
1269 if (i + 1 >= argc)
1270 not_enough("--wt");
1272 double wt;
1274 if (sscanf(argv[i + 1], "%lf", &wt) != 1)
1275 bad_arg("--wt");
1277 d2::render::set_wt(wt);
1278 i++;
1279 } else if (!strcmp(argv[i], "--3d-chain")) {
1280 if (i + 1 >= argc)
1281 not_enough("--3d-chain");
1282 d3chain_type = argv[i+1];
1283 i++;
1284 } else if (!strcmp(argv[i], "--dchain")) {
1285 if (i + 1 >= argc)
1286 not_enough("--dchain");
1287 ochain_types[0] = argv[i+1];
1288 i++;
1289 } else if (!strcmp(argv[i], "--achain")) {
1290 if (i + 1 >= argc)
1291 not_enough("--achain");
1292 achain_type = argv[i+1];
1293 i++;
1294 } else if (!strcmp(argv[i], "--afilter")) {
1295 if (i + 1 >= argc)
1296 not_enough("--afilter");
1297 afilter_type = argv[i+1];
1298 i++;
1299 } else if (!strcmp(argv[i], "--ochain")) {
1300 if (i + 2 >= argc)
1301 not_enough("--ochain");
1303 ochain = (d2::render **) local_realloc(ochain,
1304 (oc_count + 1) * sizeof(d2::render *));
1305 ochain_names = (const char **) local_realloc((void *)ochain_names,
1306 (oc_count + 1) * sizeof(const char *));
1307 ochain_types = (const char **) local_realloc((void *)ochain_types,
1308 (oc_count + 1) * sizeof(const char *));
1310 ochain_types[oc_count] = argv[i+1];
1311 ochain_names[oc_count] = argv[i+2];
1313 oc_count++;
1314 i+=2;
1315 } else if (!strcmp(argv[i], "--visp")) {
1316 if (i + 5 >= argc)
1317 not_enough("--visp");
1319 visp = (const char **) local_realloc((void *)visp, 4 *
1320 (vise_count + 1) * sizeof(const char *));
1322 for (int param = 0; param < 4; param++)
1323 visp[vise_count * 4 + param] = argv[i + 1 + param];
1325 vise_count++;
1326 i+=4;
1327 } else if (!strcmp(argv[i], "--cx")) {
1329 if (i + 1 >= argc)
1330 not_enough("--cx");
1332 sscanf(argv[i+1], "%lf", &cx_parameter);
1333 i += 1;
1335 } else if (!strcmp(argv[i], "--no-cx")) {
1336 cx_parameter = 0;
1337 } else if (!strcmp(argv[i], "--ip")) {
1338 unsupported::discontinued("--ip <r> <i>", "--lpsf box=<r> --ips <i>");
1339 } else if (!strcmp(argv[i], "--bayer")) {
1340 if (i + 1 >= argc)
1341 not_enough("--bayer");
1344 * External order is clockwise from top-left. Internal
1345 * order is counter-clockwise from top-left.
1348 if (!strcmp(argv[i+1], "rgbg")) {
1349 user_bayer = IMAGE_BAYER_RGBG;
1350 } else if (!strcmp(argv[i+1], "bgrg")) {
1351 user_bayer = IMAGE_BAYER_BGRG;
1352 } else if (!strcmp(argv[i+1], "gbgr")) {
1353 user_bayer = IMAGE_BAYER_GRGB;
1354 } else if (!strcmp(argv[i+1], "grgb")) {
1355 user_bayer = IMAGE_BAYER_GBGR;
1356 } else if (!strcmp(argv[i+1], "none")) {
1357 user_bayer = IMAGE_BAYER_NONE;
1358 } else {
1359 bad_arg("--bayer");
1361 i++;
1362 } else if (!strcmp(argv[i], "--lpsf")) {
1363 if (i + 1 >= argc)
1364 not_enough("--lpsf");
1366 psf[psf_linear] = argv[i+1];
1367 i++;
1368 } else if (!strcmp(argv[i], "--nlpsf")) {
1369 if (i + 1 >= argc)
1370 not_enough("--nlpsf");
1372 psf[psf_nonlinear] = argv[i+1];
1373 i++;
1375 } else if (!strcmp(argv[i], "--psf-match")) {
1376 if (i + 6 >= argc)
1377 not_enough("--psf-match");
1379 psf_match = 1;
1381 for (int index = 0; index < 6; index++) {
1382 if (sscanf(argv[i + 1], "%lf", &psf_match_args[index]) != 1)
1383 bad_arg("--psf-match");
1384 i++;
1387 } else if (!strcmp(argv[i], "--device")) {
1388 if (i + 1 >= argc)
1389 not_enough("--device");
1391 device = argv[i+1];
1392 i++;
1394 #if 0
1395 } else if (!strcmp(argv[i], "--usm")) {
1397 if (d3_output != NULL)
1398 unsupported::fornow("3D modeling with unsharp mask");
1400 if (i + 1 >= argc)
1401 not_enough("--usm");
1403 sscanf(argv[i+1], "%lf", &usm_multiplier);
1404 i++;
1405 #endif
1407 } else if (!strcmp(argv[i], "--ipr")) {
1409 if (i + 1 >= argc)
1410 not_enough("--ipr");
1412 if (sscanf(argv[i+1], "%d", &ip_iterations) != 1)
1413 ui::get()->error("--ipr requires an integer argument");
1415 ui::get()->warn("--ipr is deprecated. Use --ips instead");
1416 i++;
1418 } else if (!strcmp(argv[i], "--cpp-err-median")) {
1419 d3::cpf::err_median();
1420 } else if (!strcmp(argv[i], "--cpp-err-mean")) {
1421 d3::cpf::err_mean();
1422 } else if (!strcmp(argv[i], "--vp-adjust")) {
1423 d3::align::vp_adjust();
1424 } else if (!strcmp(argv[i], "--vp-noadjust")) {
1425 d3::align::vp_noadjust();
1426 } else if (!strcmp(argv[i], "--vo-adjust")) {
1427 d3::align::vo_adjust();
1428 } else if (!strcmp(argv[i], "--vo-noadjust")) {
1429 d3::align::vo_noadjust();
1430 } else if (!strcmp(argv[i], "--ip-mean")) {
1431 ip_use_median = 0;
1432 } else if (!strcmp(argv[i], "--ip-median")) {
1433 ip_use_median = 1;
1434 } else if (!strcmp(argv[i], "--ips")) {
1436 if (i + 1 >= argc)
1437 not_enough("--ips");
1439 if (sscanf(argv[i+1], "%d", &ip_iterations) != 1)
1440 ui::get()->error("--ips requires an integer argument");
1441 i++;
1442 } else if (!strcmp(argv[i], "--ipc")) {
1443 unsupported::discontinued("--ipc <c> <i>", "--ips <i> --lpsf <c>", "--ips <i> --device <c>");
1444 } else if (!strcmp(argv[i], "--exp-extend")) {
1445 d2::image_rw::exp_scale();
1446 } else if (!strcmp(argv[i], "--exp-noextend")) {
1447 d2::image_rw::exp_noscale();
1448 } else if (!strcmp(argv[i], "--exp-register")) {
1449 exposure_register = 1;
1450 d2::align::exp_register();
1451 } else if (!strcmp(argv[i], "--exp-noregister")) {
1452 exposure_register = 0;
1453 d2::align::exp_noregister();
1454 } else if (!strcmp(argv[i], "--exp-meta-only")) {
1455 exposure_register = 2;
1456 d2::align::exp_meta_only();
1457 } else if (!strcmp(argv[i], "--drizzle-only")) {
1458 unsupported::discontinued("--drizzle-only", "--dchain box:1");
1459 } else if (!strcmp(argv[i], "--subspace-traverse")) {
1460 unsupported::undocumented("--subspace-traverse");
1461 d3::scene::set_subspace_traverse();
1462 } else if (!strcmp(argv[i], "--3d-nofilter")) {
1463 d3::scene::nofilter();
1464 } else if (!strcmp(argv[i], "--3d-filter")) {
1465 d3::scene::filter();
1466 } else if (!strcmp(argv[i], "--occ-norm")) {
1467 d3::scene::nw();
1468 } else if (!strcmp(argv[i], "--occ-nonorm")) {
1469 d3::scene::no_nw();
1470 } else if (!strcmp(argv[i], "--inc")) {
1471 inc = 1;
1472 } else if (!strcmp(argv[i], "--no-inc")) {
1473 inc = 0;
1474 } else if (!strncmp(argv[i], "--exp-mult=", strlen("--exp-mult="))) {
1475 double exp_c, exp_r, exp_b;
1476 sscanf(argv[i] + strlen("--exp-mult="), "%lf,%lf,%lf", &exp_c, &exp_r, &exp_b);
1477 exp_mult = d2::pixel(1/(exp_r * exp_c), 1/exp_c, 1/(exp_b * exp_c));
1478 } else if (!strncmp(argv[i], "--visp-scale=", strlen("--visp-scale="))) {
1480 sscanf(argv[i] + strlen("--visp-scale="), "%lf", &vise_scale_factor);
1482 if (vise_scale_factor <= 0.0)
1483 ui::get()->error("VISP scale must be greater than zero");
1485 if (!finite(vise_scale_factor))
1486 ui::get()->error("VISP scale must be finite");
1488 } else if (!strncmp(argv[i], "--scale=", strlen("--scale="))) {
1490 sscanf(argv[i] + strlen("--scale="), "%lf", &scale_factor);
1492 if (scale_factor <= 0)
1493 ui::get()->error("Scale factor must be greater than zero");
1495 if (!finite(scale_factor))
1496 ui::get()->error("Scale factor must be finite");
1498 } else if (!strncmp(argv[i], "--metric=", strlen("--metric="))) {
1499 double metric;
1500 sscanf(argv[i] + strlen("--metric="), "%lf", &metric);
1501 d2::align::set_metric_exponent(metric);
1502 } else if (!strncmp(argv[i], "--threshold=", strlen("--threshold="))) {
1503 double match_threshold;
1504 sscanf(argv[i] + strlen("--threshold="), "%lf", &match_threshold);
1505 d2::align::set_match_threshold(match_threshold);
1506 } else if (!strncmp(argv[i], "--drizzle-diam=", strlen("--drizzle-diam="))) {
1507 unsupported::discontinued("--drizzle-diam=<x>", "--dchain box:1");
1508 // sscanf(argv[i] + strlen("--drizzle-diam="), "%lf", &drizzle_radius);
1509 // drizzle_radius /= 2;
1510 } else if (!strncmp(argv[i], "--perturb-upper=", strlen("--perturb-upper="))) {
1511 double perturb_upper;
1512 int characters;
1513 sscanf(argv[i] + strlen("--perturb-upper="), "%lf%n", &perturb_upper,
1514 &characters);
1515 if (*(argv[i] + strlen("--perturb-upper=") + characters) == '%')
1516 d2::align::set_perturb_upper(perturb_upper, 1);
1517 else
1518 d2::align::set_perturb_upper(perturb_upper, 0);
1519 } else if (!strncmp(argv[i], "--perturb-lower=", strlen("--perturb-lower="))) {
1520 double perturb_lower;
1521 int characters;
1522 sscanf(argv[i] + strlen("--perturb-lower="), "%lf%n", &perturb_lower,
1523 &characters);
1524 if (perturb_lower <= 0)
1525 ui::get()->error("--perturb-lower= value is non-positive");
1527 if (*(argv[i] + strlen("--perturb-lower=") + characters) == '%')
1528 d2::align::set_perturb_lower(perturb_lower, 1);
1529 else
1530 d2::align::set_perturb_lower(perturb_lower, 0);
1531 } else if (!strncmp(argv[i], "--stepsize=", strlen("--stepsize="))) {
1532 double perturb_lower;
1533 ui::get()->warn("--stepsize is deprecated. Use --perturb-lower instead");
1534 sscanf(argv[i] + strlen("--stepsize="), "%lf", &perturb_lower);
1535 d2::align::set_perturb_lower(perturb_lower, 0);
1536 } else if (!strncmp(argv[i], "--va-upper=", strlen("--va-upper="))) {
1537 double va_upper;
1538 int characters;
1539 sscanf(argv[i] + strlen("--va-upper="), "%lf%n", &va_upper,
1540 &characters);
1541 if (*(argv[i] + strlen("--va-upper=") + characters) == '%')
1542 ui::get()->error("--va-upper= does not accept '%' arguments\n");
1543 else
1544 d3::cpf::set_va_upper(va_upper);
1545 } else if (!strncmp(argv[i], "--cpp-upper=", strlen("--cpp-upper="))) {
1546 double perturb_upper;
1547 int characters;
1548 sscanf(argv[i] + strlen("--cpp-upper="), "%lf%n", &perturb_upper,
1549 &characters);
1550 if (*(argv[i] + strlen("--cpp-upper=") + characters) == '%')
1551 ui::get()->error("--cpp-upper= does not currently accept '%' arguments\n");
1552 else
1553 d3::cpf::set_cpp_upper(perturb_upper);
1554 } else if (!strncmp(argv[i], "--cpp-lower=", strlen("--cpp-lower="))) {
1555 double perturb_lower;
1556 int characters;
1557 sscanf(argv[i] + strlen("--cpp-lower="), "%lf%n", &perturb_lower,
1558 &characters);
1559 if (*(argv[i] + strlen("--cpp-lower=") + characters) == '%')
1560 ui::get()->error("--cpp-lower= does not currently accept '%' arguments\n");
1561 else
1562 d3::cpf::set_cpp_lower(perturb_lower);
1563 } else if (!strncmp(argv[i], "--hf-enhance=", strlen("--hf-enhance="))) {
1564 unsupported::discontinued("--hf-enhance=<x>");
1565 } else if (!strncmp(argv[i], "--rot-upper=", strlen("--rot-upper="))) {
1566 double rot_max;
1567 sscanf(argv[i] + strlen("--rot-upper="), "%lf", &rot_max);
1568 d2::align::set_rot_max((int) floor(rot_max));
1569 } else if (!strncmp(argv[i], "--bda-mult=", strlen("--bda-mult="))) {
1570 double bda_mult;
1571 sscanf(argv[i] + strlen("--bda-mult="), "%lf", &bda_mult);
1572 d2::align::set_bda_mult(bda_mult);
1573 } else if (!strncmp(argv[i], "--bda-rate=", strlen("--bda-rate="))) {
1574 double bda_rate;
1575 sscanf(argv[i] + strlen("--bda-rate="), "%lf", &bda_rate);
1576 d2::align::set_bda_rate(bda_rate);
1577 } else if (!strncmp(argv[i], "--lod-max=", strlen("--lod-max="))) {
1578 double lod_max;
1579 sscanf(argv[i] + strlen("--lod-max="), "%lf", &lod_max);
1580 d2::align::set_lod_max((int) floor(lod_max));
1581 } else if (!strncmp(argv[i], "--cpf-load=", strlen("--cpf-load="))) {
1582 d3::cpf::init_loadfile(argv[i] + strlen("--cpf-load="));
1583 #if 0
1584 } else if (!strncmp(argv[i], "--model-load=", strlen("--model-load="))) {
1585 d3::scene::load_model(argv[i] + strlen("--model-load="));
1586 } else if (!strncmp(argv[i], "--model-save=", strlen("--model-save="))) {
1587 d3::scene::save_model(argv[i] + strlen("--model-save="));
1588 #endif
1589 } else if (!strncmp(argv[i], "--trans-load=", strlen("--trans-load="))) {
1590 d2::tload_delete(tload);
1591 tload = d2::tload_new(argv[i] + strlen("--trans-load="));
1592 d2::align::set_tload(tload);
1593 } else if (!strncmp(argv[i], "--trans-save=", strlen("--trans-save="))) {
1594 tsave_delete(tsave);
1595 tsave = d2::tsave_new(argv[i] + strlen("--trans-save="));
1596 d2::align::set_tsave(tsave);
1597 } else if (!strncmp(argv[i], "--3d-trans-load=", strlen("--3d-trans-load="))) {
1598 d3::tload_delete(d3_tload);
1599 d3_tload = d3::tload_new(argv[i] + strlen("--3d-trans-load="));
1600 d3::align::set_tload(d3_tload);
1601 } else if (!strncmp(argv[i], "--3d-trans-save=", strlen("--3d-trans-save="))) {
1602 d3::tsave_delete(d3_tsave);
1603 d3_tsave = d3::tsave_new(argv[i] + strlen("--3d-trans-save="));
1604 d3::align::set_tsave(d3_tsave);
1605 } else {
1608 * Trap illegal options and end-of-option indicators.
1611 if (!strcmp(argv[i], "--"))
1612 i++;
1613 else if (!strncmp(argv[i], "--", strlen("--")))
1614 ui::get()->illegal_option(argv[i]);
1617 * Apply implication logic.
1620 if (extend == 0 && vise_count != 0) {
1621 implication::changed("VISP requires increased image extents.",
1622 "Image extension is now enabled.",
1623 "--extend");
1624 extend = 1;
1627 if (psf_match && ex_count)
1628 unsupported::fornow("PSF calibration with exclusion regions.");
1631 if (d3_output != NULL && ip_iterations != 0)
1632 unsupported::fornow("3D modeling with Irani-Peleg rendering");
1634 #if 0
1635 if (extend == 0 && d3_output != NULL) {
1636 implication::changed("3D modeling requires increased image extents.",
1637 "Image extension is now enabled.",
1638 "--extend");
1639 extend = 1;
1641 #endif
1643 if (cx_parameter != 0 && !exposure_register) {
1644 implication::changed("Certainty-based rendering requires exposure registration.",
1645 "Exposure registration is now enabled.",
1646 "--exp-register");
1647 d2::align::exp_register();
1648 exposure_register = 1;
1652 * Set alignment class exclusion region static variables
1655 d2::align::set_exclusion(ex_parameters, ex_count);
1658 * Initialize renderer class statics.
1661 d2::render::render_init(ex_count, ex_parameters, ex_show, extend, scale_factor);
1664 * Set confidence
1667 d2::exposure::set_confidence(cx_parameter);
1670 * Keep transformations for Irani-Peleg, psf-match, and
1671 * VISE
1674 if (ip_iterations > 0 || psf_match || vise_count > 0) {
1675 d2::align::keep();
1679 * Initialize device-specific variables
1682 d2::psf *device_response[psf_N] = { NULL, NULL };
1683 d2::exposure **input_exposure = NULL;
1684 ale_pos view_angle = 43.7 * M_PI / 180;
1685 // ale_pos view_angle = 90 * M_PI / 180;
1686 input_exposure = (d2::exposure **)
1687 malloc((argc - i - 1) * sizeof(d2::exposure *));
1689 if (device != NULL) {
1690 if (!strcmp(device, "xvp610_640x480")) {
1691 device_response[psf_linear] = new xvp610_640x480::lpsf();
1692 device_response[psf_nonlinear] = new xvp610_640x480::nlpsf();
1693 for (int ii = 0; ii < argc - i - 1; ii++)
1694 input_exposure[ii] = new xvp610_640x480::exposure();
1695 view_angle = xvp610_640x480::view_angle();
1696 } else if (!strcmp(device, "xvp610_320x240")) {
1697 device_response[psf_linear] = new xvp610_320x240::lpsf();
1698 device_response[psf_nonlinear] = new xvp610_320x240::nlpsf();
1699 for (int ii = 0; ii < argc - i - 1; ii++)
1700 input_exposure[ii] = new xvp610_320x240::exposure();
1701 view_angle = xvp610_320x240::view_angle();
1702 } else if (!strcmp(device, "ov7620_raw_linear")) {
1703 device_response[psf_linear] = new ov7620_raw_linear::lpsf();
1704 device_response[psf_nonlinear] = NULL;
1705 for (int ii = 0; ii < argc - i - 1; ii++)
1706 input_exposure[ii] = new ov7620_raw_linear::exposure();
1707 d2::image_rw::set_default_bayer(IMAGE_BAYER_BGRG);
1708 } else if (!strcmp(device, "canon_300d_raw_linear")) {
1709 device_response[psf_linear] = new canon_300d_raw_linear::lpsf();
1710 device_response[psf_nonlinear] = NULL;
1711 for (int ii = 0; ii < argc - i - 1; ii++)
1712 input_exposure[ii] = new canon_300d_raw_linear::exposure();
1713 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1714 } else if (!strcmp(device, "canon_300d_raw_linear+85mm_1.8")) {
1715 device_response[psf_linear] = new canon_300d_raw_linear_85mm_1_8::lpsf();
1716 device_response[psf_nonlinear] = NULL;
1717 for (int ii = 0; ii < argc - i - 1; ii++)
1718 input_exposure[ii] = new canon_300d_raw_linear_85mm_1_8::exposure();
1719 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1720 view_angle = canon_300d_raw_linear_85mm_1_8::view_angle();
1721 } else if (!strcmp(device, "canon_300d_raw_linear+50mm_1.8")) {
1722 device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_8::lpsf();
1723 device_response[psf_nonlinear] = NULL;
1724 for (int ii = 0; ii < argc - i - 1; ii++)
1725 input_exposure[ii] = new canon_300d_raw_linear_50mm_1_8::exposure();
1726 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1727 view_angle = canon_300d_raw_linear_50mm_1_8::view_angle();
1728 } else if (!strcmp(device, "canon_300d_raw_linear+50mm_1.4")) {
1729 device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_4::lpsf();
1730 device_response[psf_nonlinear] = NULL;
1731 for (int ii = 0; ii < argc - i - 1; ii++)
1732 input_exposure[ii] = new canon_300d_raw_linear_50mm_1_4::exposure();
1733 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1734 view_angle = canon_300d_raw_linear_50mm_1_4::view_angle();
1735 } else if (!strcmp(device, "canon_300d_raw_linear+50mm_1.4@1.4")) {
1736 device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_4_1_4::lpsf();
1737 device_response[psf_nonlinear] = NULL;
1738 for (int ii = 0; ii < argc - i - 1; ii++)
1739 input_exposure[ii] = new canon_300d_raw_linear_50mm_1_4_1_4::exposure();
1740 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1741 view_angle = canon_300d_raw_linear_50mm_1_4_1_4::view_angle();
1742 } else {
1743 ui::get()->unknown_device(device);
1745 } else {
1746 for (int ii = 0; ii < argc - i - 1; ii++)
1747 input_exposure[ii] = new d2::exposure_default();
1751 * User-specified variables.
1754 if (user_view_angle != 0) {
1755 view_angle = user_view_angle;
1758 if (user_bayer != IMAGE_BAYER_DEFAULT) {
1759 d2::image_rw::set_default_bayer(user_bayer);
1763 * PSF-match exposure.
1765 if (psf_match) {
1766 delete input_exposure[argc - i - 2];
1767 input_exposure[argc - i - 2] = new d2::exposure_default();
1771 * Initialize output exposure
1774 d2::exposure *output_exposure = new d2::exposure_default();
1775 output_exposure->set_multiplier(exp_mult);
1778 * Configure the response function.
1781 d2::psf *response[2] = {NULL, NULL};
1783 for (int n = 0; n < psf_N; n++ ) {
1784 if (psf[n] != NULL) {
1786 response[n] = d2::psf_parse::get((n == psf_linear), psf[n]);
1788 } else if (device_response[n] != NULL) {
1791 * Device-specific response
1794 response[n] = device_response[n];
1796 } else {
1799 * Default point-spread function.
1802 if (n == psf_linear) {
1805 * Default lpsf is a box filter
1806 * of diameter 1.0 (radius
1807 * 0.5).
1810 response[n] = new d2::box(0.5);
1812 } else if (n == psf_nonlinear) {
1815 * nlpsf is disabled by default.
1818 response[n] = NULL;
1824 * First file argument. Print general file information as well
1825 * as information specific to this argument. Initialize image
1826 * file handler.
1830 * There should be at least two file arguments.
1833 if (i >= argc - 1) {
1834 hi.usage();
1835 exit(1);
1838 d2::image_rw::init(argc - i - 1, argv + i, argv[argc - 1], input_exposure, output_exposure);
1839 ochain_names[0] = argv[argc - 1];
1842 * Handle control point data for alignment
1844 d2::align::set_cp_count(d3::cpf::count());
1845 for (unsigned int ii = 0; ii < d3::cpf::count(); ii++)
1846 d2::align::set_cp(ii, d3::cpf::get_2d(ii));
1849 * PSF-match bayer patterns.
1852 if (psf_match) {
1853 d2::image_rw::set_specific_bayer(argc - i - 2, IMAGE_BAYER_NONE);
1857 * Handle alignment weight map, if necessary
1860 if (wm_filename != NULL) {
1861 d2::image *weight_map;
1862 weight_map = d2::image_rw::read_image(wm_filename, new d2::exposure_linear());
1863 weight_map->set_offset(wm_offsety, wm_offsetx);
1864 d2::align::set_weight_map(weight_map);
1868 * Write comment information about original frame and
1869 * target image to the transformation save file, if we
1870 * have one.
1873 const d2::image *im = d2::image_rw::open(0);
1874 tsave_orig(tsave, argv[i], im->avg_channel_magnitude());
1875 tsave_target(tsave, argv[argc - 1]);
1876 d2::image_rw::close(0);
1879 * Initialize alignment interpolant.
1882 if (afilter_type != "internal")
1883 d2::align::set_interpolant(d2::render_parse::get_SSF(afilter_type));
1886 * Initialize achain and ochain.
1889 achain = d2::render_parse::get(achain_type);
1891 for (int chain = 0; chain < oc_count; chain++)
1892 ochain[chain] = d2::render_parse::get(ochain_types[chain]);
1895 * Use merged renderings as reference images in
1896 * alignment.
1899 d2::align::set_reference(achain);
1902 * Tell the alignment class about the scale factor.
1905 d2::align::set_scale(scale_factor);
1908 * Initialize visp.
1911 d2::vise_core::set_scale(vise_scale_factor);
1913 for (int opt = 0; opt < vise_count; opt++) {
1914 d2::vise_core::add(d2::render_parse::get(visp[opt * 4 + 0]),
1915 visp[opt * 4 + 1],
1916 visp[opt * 4 + 2],
1917 visp[opt * 4 + 3]);
1921 * Initialize non-incremental renderers
1924 #if 0
1925 if (usm_multiplier != 0) {
1928 * Unsharp Mask renderer
1931 ochain[0] = new d2::usm(ochain[0], scale_factor,
1932 usm_multiplier, inc, response[psf_linear],
1933 response[psf_nonlinear], &input_exposure[0]);
1935 #endif
1937 if (psf_match) {
1940 * Point-spread function calibration renderer.
1941 * This renderer does not produce image output.
1942 * It is reserved for use with the point-spread
1943 * function calibration script
1944 * ale-psf-calibrate.
1947 ochain[0] = new d2::psf_calibrate(ochain[0],
1948 1, inc, response[psf_linear],
1949 response[psf_nonlinear],
1950 psf_match_args);
1952 } else if (ip_iterations != 0) {
1955 * Irani-Peleg renderer
1958 ochain[0] = new d2::ipc( ochain[0], ip_iterations,
1959 inc, response[psf_linear],
1960 response[psf_nonlinear],
1961 (exposure_register == 1), ip_use_median);
1965 * Handle the original frame.
1968 ui::get()->original_frame_start(argv[i]);
1970 for (int opt = 0; opt < oc_count; opt++) {
1971 ui::get()->set_orender_current(opt);
1972 ochain[opt]->sync(0);
1973 if (inc) {
1974 ui::get()->writing_output(opt);
1975 d2::image_rw::write_image(ochain_names[opt],
1976 ochain[opt]->get_image(0));
1980 d2::vise_core::frame_queue_add(0);
1982 ui::get()->original_frame_done();
1985 * Handle supplemental frames.
1988 for (unsigned int j = 1; j < d2::image_rw::count(); j++) {
1990 const char *name = d2::image_rw::name(j);
1992 ui::get()->supplemental_frame_start(name);
1995 * Write comment information about the
1996 * supplemental frame to the transformation
1997 * save file, if we have one.
2000 tsave_info (tsave, name);
2002 const d2::image *im = d2::image_rw::open(j);
2003 d2::pixel apm = im->avg_channel_magnitude();
2004 tsave_apm(tsave, apm[0], apm[1], apm[2]);
2005 d2::image_rw::close(j);
2007 for (int opt = 0; opt < oc_count; opt++) {
2008 ui::get()->set_orender_current(opt);
2009 ochain[opt]->sync(j);
2010 if (inc) {
2011 ui::get()->writing_output(opt);
2012 d2::image_rw::write_image(ochain_names[opt],
2013 ochain[opt]->get_image(j));
2017 d2::vise_core::frame_queue_add(j);
2019 ui::get()->supplemental_frame_done();
2023 * Do any post-processing and output final image
2025 * XXX: note that non-incremental renderers currently
2026 * return zero for ochain[0]->sync(), since they write
2027 * output internally when inc != 0.
2030 for (int opt = 0; opt < oc_count; opt++)
2031 if ((ochain[opt]->sync() || !inc) && !psf_match)
2032 d2::image_rw::write_image(ochain_names[opt], ochain[opt]->get_image());
2035 * Output a summary match statistic.
2038 ui::get()->ale_2d_done((double) d2::align::match_summary());
2041 * Perform any 3D tasks
2044 optimizations::begin_3d_work();
2046 if (d3_count > 0) {
2048 ui::get()->d3_start();
2050 d3::align::init_angle(view_angle);
2052 ui::get()->d3_init_view_angle(view_angle / M_PI * 180);
2054 d3::align::init_from_d2();
2056 if (d3::cpf::count() > 0) {
2057 ui::get()->d3_control_point_solve();
2058 d3::cpf::solve_3d();
2059 ui::get()->d3_control_point_solve_done();
2062 ui::get()->d3_final_view_angle(d3::align::angle_of(0) / M_PI * 180);
2064 d3::align::write_alignments();
2066 d3::scene::set_filter_type(d3chain_type);
2068 d3::scene::init_from_d2();
2070 ui::get()->d3_subdividing_space();
2071 d3::scene::make_space(d3_depth, d3_output, &d3_depth_pt, &d3_output_pt);
2072 ui::get()->d3_subdividing_space_done();
2074 ui::get()->d3_updating_occupancy();
2075 d3::scene::reduce_cost_to_search_depth(output_exposure, inc);
2076 ui::get()->d3_updating_occupancy_done();
2078 d3::scene::d3px(d3px_count, d3px_parameters);
2079 int view_count = 0;
2080 for (unsigned int i = 0; i < d2::image_rw::count(); i++) {
2081 assert (i < d3_count);
2083 if (d3_depth[i] != NULL) {
2084 ui::get()->d3_writing_output(d3_depth[i]);
2085 ui::get()->d3_render_status(0, 0, -1, -1, -1, -1, 0);
2086 const d2::image *im = d3::scene::depth(i);
2087 d2::image_rw::write_image(d3_depth[i], im, output_exposure, 1, 1);
2088 delete im;
2089 ui::get()->d3_writing_output_done();
2092 if (d3_output[i] != NULL) {
2093 ui::get()->d3_writing_output(d3_output[i]);
2094 const d2::image *im = d3::scene::view(i);
2095 d2::image_rw::write_image(d3_output[i], im, output_exposure);
2096 delete im;
2097 d3::focus::set_camera(view_count++);
2098 ui::get()->d3_writing_output_done();
2101 for (std::map<const char *, d3::pt>::iterator i = d3_output_pt.begin();
2102 i != d3_output_pt.end(); i++) {
2104 ui::get()->d3_writing_output(i->first);
2105 const d2::image *im = d3::scene::view(i->second);
2106 d2::image_rw::write_image(i->first, im, output_exposure);
2107 delete im;
2108 d3::focus::set_camera(view_count++);
2109 ui::get()->d3_writing_output_done();
2112 for (std::map<const char *, d3::pt>::iterator i = d3_depth_pt.begin();
2113 i != d3_depth_pt.end(); i++) {
2115 ui::get()->d3_writing_output(i->first);
2116 ui::get()->d3_render_status(0, 0, -1, -1, -1, -1, 0);
2117 const d2::image *im = d3::scene::depth(i->second);
2118 d2::image_rw::write_image(i->first, im, output_exposure, 1, 1);
2119 delete im;
2120 ui::get()->d3_writing_output_done();
2124 for (unsigned int i = d2::image_rw::count(); i < d3_count; i++) {
2125 if (d3_depth[i] != NULL) {
2126 fprintf(stderr, "\n\n*** Frame number for --3dd too high. ***\n\n");
2128 if (d3_output[i] != NULL) {
2129 fprintf(stderr, "\n\n*** Frame number for --3dv too high. ***\n\n");
2135 * Destroy the image file handler
2138 d2::image_rw::destroy();
2141 * Delete the transformation file structures, if any
2142 * exist.
2145 tsave_delete(tsave);
2146 tload_delete(tload);
2149 * We're done.
2152 exit(0);
2157 * If there was no output, the user might need more information.
2160 hi.usage();
2161 exit(1);