Fix dimension comparison bug in d3::space::traverse::get_next_split()
[Ale.git] / ale.cc
blob574b9d93d14cb0e45edb7f13be04280ffc144f20
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 = "zero";
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 * Iterate through arguments until we reach the first file
428 * argument. After the first file argument, we assume that
429 * all following arguments are files.
432 for (int i = 1; i < argc - 1; i++) {
435 if (!strcmp(argv[i], "--q0")
436 || !strcmp(argv[i], "--q1")
437 || !strcmp(argv[i], "--q2")
438 || !strcmp(argv[i], "--qr")
439 || !strcmp(argv[i], "--qn")) {
441 * Do nothing. Defaults have already been set.
443 } else if (!strcmp(argv[i], "--8bpc")) {
444 d2::image_rw::depth8();
445 } else if (!strcmp(argv[i], "--16bpc")) {
446 d2::image_rw::depth16();
447 } else if (!strcmp(argv[i], "--plain")) {
448 d2::image_rw::ppm_plain();
449 } else if (!strcmp(argv[i], "--raw")) {
450 d2::image_rw::ppm_raw();
451 } else if (!strcmp(argv[i], "--auto")) {
452 d2::image_rw::ppm_auto();
453 } else if (!strcmp(argv[i], "--align-all")) {
454 d2::align::all();
455 } else if (!strcmp(argv[i], "--align-green")) {
456 d2::align::green();
457 } else if (!strcmp(argv[i], "--align-sum")) {
458 d2::align::sum();
459 } else if (!strcmp(argv[i], "--translation")) {
460 d2::align::class_translation();
461 } else if (!strcmp(argv[i], "--euclidean")) {
462 d2::align::class_euclidean();
463 } else if (!strcmp(argv[i], "--projective")) {
464 d2::align::class_projective();
465 } else if (!strcmp(argv[i], "--identity")) {
466 d2::align::initial_default_identity();
467 } else if (!strcmp(argv[i], "--follow")) {
468 d2::align::initial_default_follow();
469 } else if (!strcmp(argv[i], "--perturb-output")) {
470 d2::align::perturb_output();
471 } else if (!strcmp(argv[i], "--perturb-source")) {
472 d2::align::perturb_source();
473 } else if (!strcmp(argv[i], "--fail-optimal")) {
474 d2::align::fail_optimal();
475 } else if (!strcmp(argv[i], "--fail-default")) {
476 d2::align::fail_default();
477 } else if (!strcmp(argv[i], "--no-extend")) {
478 extend = 0;
479 } else if (!strcmp(argv[i], "--extend")) {
480 extend = 1;
481 } else if (!strcmp(argv[i], "--no-mc")) {
482 d2::align::no_mc();
483 } else if (!strcmp(argv[i], "--oc")) {
484 d3::scene::oc();
485 } else if (!strcmp(argv[i], "--no-oc")) {
486 d3::scene::no_oc();
487 } else if (!strcmp(argv[i], "--gs")) {
488 if (i + 1 >= argc)
489 not_enough("--gs");
491 d2::align::gs(argv[i+1]);
492 i += 1;
494 } else if (!strcmp(argv[i], "--gs-mo")) {
495 if (i + 1 >= argc)
496 not_enough("--gs-mo");
498 unsigned int mo_parameter;
499 if (sscanf(argv[i+1], "%u", &mo_parameter) != 1)
500 bad_arg("--gs-mo");
502 d2::align::gs_mo(mo_parameter);
503 i += 1;
505 } else if (!strcmp(argv[i], "--3ddp") || !strcmp(argv[i], "--3dvp")) {
506 d2::align::keep();
509 * Unsupported configurations
512 if (ip_iterations)
513 unsupported::fornow("3D modeling with Irani-Peleg rendering");
515 #if 0
516 if (usm_multiplier)
517 unsupported::fornow("3D modeling with unsharp mask");
518 #endif
521 * Check for argument availability
524 if (i + 10 >= argc)
525 not_enough(argv[i]);
528 * Initialize if necessary
530 * Note: because their existence is checked as an
531 * indicator of the presence of 3D arguments, we
532 * initialize these structures here.
535 if (d3_output == NULL) {
536 d3_count = argc - (i + 2) - 1;
537 d3_output = (const char **) calloc(d3_count, sizeof(char *));
538 d3_depth = (const char **) calloc(d3_count, sizeof(char *));
541 unsigned int width, height;
542 double view_angle;
543 double x, y, z;
544 double P, Y, R;
546 if (sscanf(argv[i+1], "%u", &width) != 1
547 || sscanf(argv[i+2], "%u", &height) != 1
548 || sscanf(argv[i+3], "%lf", &view_angle) != 1
549 || sscanf(argv[i+4], "%lf", &x) != 1
550 || sscanf(argv[i+5], "%lf", &y) != 1
551 || sscanf(argv[i+6], "%lf", &z) != 1
552 || sscanf(argv[i+7], "%lf", &P) != 1
553 || sscanf(argv[i+8], "%lf", &Y) != 1
554 || sscanf(argv[i+9], "%lf", &R) != 1)
555 bad_arg(argv[i]);
557 view_angle *= M_PI / 180;
558 P *= M_PI / 180;
559 Y *= M_PI / 180;
560 R *= M_PI / 180;
562 d2::transformation t =
563 d2::transformation::eu_identity();
564 t.set_domain(height, width);
565 d3::pt _pt(t, d3::et(y, x, z, Y, P, R), view_angle);
567 if (!strcmp(argv[i], "--3dvp")) {
568 d3_output_pt[argv[i+10]] = _pt;
569 } else if (!strcmp(argv[i], "--3ddp")) {
570 d3_depth_pt[argv[i+10]] = _pt;
571 } else {
572 assert(0);
575 i+=10;
576 } else if (!strcmp(argv[i], "--3dv")) {
577 d2::align::keep();
579 unsigned int frame_no;
582 * Unsupported configurations
585 if (ip_iterations)
586 unsupported::fornow("3D modeling with Irani-Peleg rendering");
588 #if 0
589 if (usm_multiplier)
590 unsupported::fornow("3D modeling with unsharp mask");
591 #endif
594 * Check for argument availability
597 if (i + 2 >= argc)
598 not_enough("--3dv");
601 * Initialize if necessary
604 if (d3_output == NULL) {
605 d3_count = argc - (i + 2) - 1;
606 d3_output = (const char **) calloc(d3_count, sizeof(char *));
607 d3_depth = (const char **) calloc(d3_count, sizeof(char *));
610 if (sscanf(argv[i+1], "%d", &frame_no) != 1)
611 ui::get()->error("--3dv argument 0 must be an integer");
613 if (frame_no >= d3_count)
614 ui::get()->error("--3dv argument 0 is too large");
616 if (d3_output[frame_no] != NULL) {
617 unsupported::fornow ("Writing a single 3D view to more than one output file");
620 d3_output[frame_no] = argv[i+2];
622 i+=2;
623 } else if (!strcmp(argv[i], "--3dd")) {
624 d2::align::keep();
626 unsigned int frame_no;
629 * Unsupported configurations
632 if (ip_iterations)
633 unsupported::fornow("3D modeling with Irani-Peleg rendering");
635 #if 0
636 if (usm_multiplier)
637 unsupported::fornow("3D modeling with unsharp mask");
638 #endif
641 * Check for argument availability
644 if (i + 2 >= argc)
645 not_enough("--3dd");
648 * Initialize if necessary
651 if (d3_output == NULL) {
652 d3_count = argc - (i + 2) - 1;
653 d3_output = (const char **) calloc(d3_count, sizeof(char *));
654 d3_depth = (const char **) calloc(d3_count, sizeof(char *));
657 if (sscanf(argv[i+1], "%d", &frame_no) != 1)
658 ui::get()->error("--3dd argument 0 must be an integer");
660 if (frame_no >= d3_count)
661 ui::get()->error("--3dd argument 0 is too large");
663 if (d3_depth[frame_no] != NULL) {
664 unsupported::fornow ("Writing a single frame's depth info to more than one output file");
667 d3_depth[frame_no] = argv[i+2];
669 i+=2;
671 } else if (!strcmp(argv[i], "--view-angle")) {
672 if (i + 1 >= argc)
673 not_enough("--view-angle");
675 double va_parameter;
676 sscanf(argv[i+1], "%lf", &va_parameter);
677 i += 1;
678 user_view_angle = va_parameter * M_PI / 180;
679 } else if (!strcmp(argv[i], "--cpf-load")) {
680 if (i + 1 >= argc)
681 not_enough("--cpf-load");
683 d3::cpf::init_loadfile(argv[i+1]);
684 i += 1;
685 } else if (!strcmp(argv[i], "--ui=stream")) {
686 ui::set_stream();
687 } else if (!strcmp(argv[i], "--ui=tty")) {
688 ui::set_tty();
689 } else if (!strcmp(argv[i], "--et")) {
691 if (i + 1 >= argc)
692 not_enough("--et");
694 double et_parameter;
695 sscanf(argv[i+1], "%lf", &et_parameter);
696 i += 1;
697 d3::scene::et(et_parameter);
699 } else if (!strcmp(argv[i], "--st")) {
700 if (i + 1 >= argc)
701 not_enough("--st");
703 double st_parameter;
704 sscanf(argv[i+1], "%lf", &st_parameter);
705 i += 1;
706 d3::cpf::st(st_parameter);
707 } else if (!strcmp(argv[i], "--di-lower")) {
708 if (i + 1 >= argc)
709 not_enough("--di-lower");
711 double di_parameter;
712 sscanf(argv[i+1], "%lf", &di_parameter);
713 i += 1;
714 d3::scene::di_lower(di_parameter);
715 } else if (!strcmp(argv[i], "--rc")) {
716 if (i + 1 >= argc)
717 not_enough("--rc");
719 double rc_parameter;
720 sscanf(argv[i+1], "%lf", &rc_parameter);
721 i += 1;
722 d3::scene::rc(rc_parameter);
723 } else if (!strcmp(argv[i], "--do-try")) {
724 if (i + 1 >= argc)
725 not_enough("--do-try");
727 double do_parameter;
728 sscanf(argv[i+1], "%lf", &do_parameter);
729 i += 1;
730 d3::scene::do_try(do_parameter);
731 } else if (!strcmp(argv[i], "--di-upper")) {
732 if (i + 1 >= argc)
733 not_enough("--di-upper");
735 double dgi_parameter;
736 sscanf(argv[i+1], "%lf", &dgi_parameter);
737 i += 1;
738 d3::scene::di_upper(dgi_parameter);
739 } else if (!strcmp(argv[i], "--fc")) {
740 if (i + 1 >= argc)
741 not_enough("--fc");
743 double fc_parameter;
744 sscanf(argv[i+1], "%lf", &fc_parameter);
745 i += 1;
746 d3::scene::fc(fc_parameter);
747 } else if (!strcmp(argv[i], "--ecm")) {
748 unsupported::discontinued("--ecm <x>");
749 } else if (!strcmp(argv[i], "--acm")) {
750 unsupported::discontinued("--acm <x>");
751 } else if (!strcmp(argv[i], "--def-nn")) {
752 if (i + 1 >= argc)
753 not_enough("--def-nn");
755 double nn_parameter;
756 sscanf(argv[i+1], "%lf", &nn_parameter);
757 i += 1;
758 d2::image_rw::def_nn(nn_parameter);
760 if (nn_parameter > 2) {
761 fprintf(stderr, "\n\n*** Warning: --def-nn implementation is currently "
762 "inefficient for large radii. ***\n\n");
765 } else if (!strcmp(argv[i], "--mc")) {
766 if (i + 1 >= argc)
767 not_enough("--mc");
769 double mc_parameter;
770 sscanf(argv[i+1], "%lf", &mc_parameter);
771 mc_parameter /= 100;
772 i += 1;
773 d2::align::mc(mc_parameter);
775 } else if (!strcmp(argv[i], "--fx")) {
777 if (i + 1 >= argc)
778 not_enough("--fx");
780 double fx_parameter;
781 sscanf(argv[i+1], "%lf", &fx_parameter);
782 i += 1;
783 d3::scene::fx(fx_parameter);
785 } else if (!strcmp(argv[i], "--tcem")) {
787 if (i + 1 >= argc)
788 not_enough("--tcem");
790 double tcem_parameter;
791 sscanf(argv[i+1], "%lf", &tcem_parameter);
792 i += 1;
793 d3::scene::tcem(tcem_parameter);
795 } else if (!strcmp(argv[i], "--oui")) {
797 if (i + 1 >= argc)
798 not_enough("--oui");
800 unsigned int oui_parameter;
801 sscanf(argv[i+1], "%u", &oui_parameter);
802 i += 1;
803 d3::scene::oui(oui_parameter);
805 } else if (!strcmp(argv[i], "--pa")) {
807 if (i + 1 >= argc)
808 not_enough("--pa");
810 unsigned int pa_parameter;
811 sscanf(argv[i+1], "%u", &pa_parameter);
812 i += 1;
813 d3::scene::pa(pa_parameter);
815 } else if (!strcmp(argv[i], "--pc")) {
817 if (i + 1 >= argc)
818 not_enough("--pc");
820 d3::scene::pc(argv[i+1]);
821 i += 1;
823 } else if (!strcmp(argv[i], "--cw")) {
824 d2::align::certainty_weighted(1);
825 } else if (!strcmp(argv[i], "--no-cw")) {
826 d2::align::certainty_weighted(0);
827 } else if (!strcmp(argv[i], "--wm")) {
828 if (wm_filename != NULL)
829 ui::get()->error("only one weight map can be specified");
831 if (i + 3 >= argc)
832 not_enough("--wm");
833 wm_filename = argv[i+1];
835 if (sscanf(argv[i+2], "%d", &wm_offsetx) != 1)
836 ui::get()->error("--wm x-argument must be an integer");
838 if (sscanf(argv[i+3], "%d", &wm_offsety) != 1)
839 ui::get()->error("--wm y-argument must be an integer");
841 i += 3;
843 } else if (!strcmp(argv[i], "--fl")) {
844 if (i + 3 >= argc)
845 not_enough("--fl");
846 double h, v, a;
847 if (sscanf(argv[i+1], "%lf", &h) != 1)
848 ui::get()->error("--fl h-argument must be numerical");
849 if (sscanf(argv[i+2], "%lf", &v) != 1)
850 ui::get()->error("--fl v-argument must be numerical");
851 if (sscanf(argv[i+3], "%lf", &a) != 1)
852 ui::get()->error("--fl a-argument must be numerical");
853 i += 3;
854 #ifdef USE_FFTW
855 d2::align::set_frequency_cut(h, v, a);
856 #else
857 ui::get()->error_hint("--fl is not supported", "rebuild ALE with FFTW=1");
858 #endif
859 } else if (!strcmp(argv[i], "--wmx")) {
860 if (i + 3 >= argc)
861 not_enough("--wmx");
862 #ifdef USE_UNIX
863 d2::align::set_wmx(argv[i+1], argv[i+2], argv[i+3]);
864 #else
865 ui::get()->error_hint("--wmx is not supported", "rebuild ALE with POSIX=1");
866 #endif
867 i += 3;
868 } else if (!strcmp(argv[i], "--flshow")) {
869 if (i + 1 >= argc)
870 not_enough("--flshow");
871 d2::align::set_fl_show(argv[i+1]);
872 i++;
873 } else if (!strcmp(argv[i], "--3dpx")) {
874 if (i + 6 >= argc)
875 not_enough("--3dpx");
877 d3px_parameters = (double *) local_realloc(d3px_parameters, (d3px_count + 1) * 6 * sizeof(double));
879 for (int param = 0; param < 6; param++)
880 if (sscanf(argv[i + param + 1], "%lf", &(d3px_parameters[6 * d3px_count + param])) != 1)
881 bad_arg("--d3px");
884 * Swap x and y, since their internal meanings differ from their external meanings.
887 for (int param = 0; param < 2; param++) {
888 double temp = d3px_parameters[6 * d3px_count + 2 + param];
889 d3px_parameters[6 * d3px_count + 2 + param] = d3px_parameters[6 * d3px_count + 0 + param];
890 d3px_parameters[6 * d3px_count + 0 + param] = temp;
895 * Increment counters
898 d3px_count++;
899 i += 6;
900 } else if (!strcmp(argv[i], "--ex")) {
901 if (i + 6 >= argc)
902 not_enough("--ex");
904 ex_parameters = (int *) local_realloc(ex_parameters, (ex_count + 1) * 6 * sizeof(int));
906 for (int param = 0; param < 6; param++)
907 if (sscanf(argv[i + param + 1], "%d", &(ex_parameters[6 * ex_count + param])) != 1)
908 bad_arg("--ex");
911 * Swap x and y, since their internal meanings differ from their external meanings.
914 for (int param = 0; param < 2; param++) {
915 int temp = ex_parameters[6 * ex_count + 2 + param];
916 ex_parameters[6 * ex_count + 2 + param] = ex_parameters[6 * ex_count + 0 + param];
917 ex_parameters[6 * ex_count + 0 + param] = temp;
922 * Increment counters
925 ex_count++;
926 i += 6;
927 } else if (!strcmp(argv[i], "--crop")) {
928 if (i + 6 >= argc)
929 not_enough("--crop");
931 ex_parameters = (int *) local_realloc(ex_parameters, (ex_count + 4) * 6 * sizeof(int));
932 int crop_args[6];
934 for (int param = 0; param < 6; param++)
935 if (sscanf(argv[i + param + 1], "%d", &(crop_args[param])) != 1)
936 bad_arg("--crop");
939 * Construct exclusion regions from the crop area,
940 * swapping x and y, since their internal meanings
941 * differ from their external meanings.
945 * Exclusion region 1: low x
948 ex_parameters[6 * ex_count + 0] = INT_MIN;
949 ex_parameters[6 * ex_count + 1] = crop_args[2] - 1;
950 ex_parameters[6 * ex_count + 2] = INT_MIN;
951 ex_parameters[6 * ex_count + 3] = INT_MAX;
952 ex_parameters[6 * ex_count + 4] = crop_args[4];
953 ex_parameters[6 * ex_count + 5] = crop_args[5];
956 * Exclusion region 2: low y
959 ex_parameters[6 * ex_count + 6] = INT_MIN;
960 ex_parameters[6 * ex_count + 7] = INT_MAX;
961 ex_parameters[6 * ex_count + 8] = INT_MIN;
962 ex_parameters[6 * ex_count + 9] = crop_args[0] - 1;
963 ex_parameters[6 * ex_count + 10] = crop_args[4];
964 ex_parameters[6 * ex_count + 11] = crop_args[5];
967 * Exclusion region 3: high y
970 ex_parameters[6 * ex_count + 12] = INT_MIN;
971 ex_parameters[6 * ex_count + 13] = INT_MAX;
972 ex_parameters[6 * ex_count + 14] = crop_args[1] + 1;
973 ex_parameters[6 * ex_count + 15] = INT_MAX;
974 ex_parameters[6 * ex_count + 16] = crop_args[4];
975 ex_parameters[6 * ex_count + 17] = crop_args[5];
978 * Exclusion region 4: high x
981 ex_parameters[6 * ex_count + 18] = crop_args[3] + 1;
982 ex_parameters[6 * ex_count + 19] = INT_MAX;
983 ex_parameters[6 * ex_count + 20] = INT_MIN;
984 ex_parameters[6 * ex_count + 21] = INT_MAX;
985 ex_parameters[6 * ex_count + 22] = crop_args[4];
986 ex_parameters[6 * ex_count + 23] = crop_args[5];
989 * Increment counters
992 ex_count += 4;
993 i += 6;
994 } else if (!strcmp(argv[i], "--exshow")) {
995 ex_show = 1;
996 } else if (!strcmp(argv[i], "--wt")) {
997 if (i + 1 >= argc)
998 not_enough("--wt");
1000 double wt;
1002 if (sscanf(argv[i + 1], "%lf", &wt) != 1)
1003 bad_arg("--wt");
1005 d2::render::set_wt(wt);
1006 i++;
1007 } else if (!strcmp(argv[i], "--3d-chain")) {
1008 if (i + 1 >= argc)
1009 not_enough("--3d-chain");
1010 d3chain_type = argv[i+1];
1011 i++;
1012 } else if (!strcmp(argv[i], "--dchain")) {
1013 if (i + 1 >= argc)
1014 not_enough("--dchain");
1015 ochain_types[0] = argv[i+1];
1016 i++;
1017 } else if (!strcmp(argv[i], "--achain")) {
1018 if (i + 1 >= argc)
1019 not_enough("--achain");
1020 achain_type = argv[i+1];
1021 i++;
1022 } else if (!strcmp(argv[i], "--afilter")) {
1023 if (i + 1 >= argc)
1024 not_enough("--afilter");
1025 afilter_type = argv[i+1];
1026 i++;
1027 } else if (!strcmp(argv[i], "--ochain")) {
1028 if (i + 2 >= argc)
1029 not_enough("--ochain");
1031 ochain = (d2::render **) local_realloc(ochain,
1032 (oc_count + 1) * sizeof(d2::render *));
1033 ochain_names = (const char **) local_realloc((void *)ochain_names,
1034 (oc_count + 1) * sizeof(const char *));
1035 ochain_types = (const char **) local_realloc((void *)ochain_types,
1036 (oc_count + 1) * sizeof(const char *));
1038 ochain_types[oc_count] = argv[i+1];
1039 ochain_names[oc_count] = argv[i+2];
1041 oc_count++;
1042 i+=2;
1043 } else if (!strcmp(argv[i], "--visp")) {
1044 if (i + 5 >= argc)
1045 not_enough("--visp");
1047 visp = (const char **) local_realloc((void *)visp, 4 *
1048 (vise_count + 1) * sizeof(const char *));
1050 for (int param = 0; param < 4; param++)
1051 visp[vise_count * 4 + param] = argv[i + 1 + param];
1053 vise_count++;
1054 i+=4;
1055 } else if (!strcmp(argv[i], "--cx")) {
1057 if (i + 1 >= argc)
1058 not_enough("--cx");
1060 sscanf(argv[i+1], "%lf", &cx_parameter);
1061 i += 1;
1063 } else if (!strcmp(argv[i], "--no-cx")) {
1064 cx_parameter = 0;
1065 } else if (!strcmp(argv[i], "--ip")) {
1066 unsupported::discontinued("--ip <r> <i>", "--lpsf box=<r> --ips <i>");
1067 } else if (!strcmp(argv[i], "--bayer")) {
1068 if (i + 1 >= argc)
1069 not_enough("--bayer");
1072 * External order is clockwise from top-left. Internal
1073 * order is counter-clockwise from top-left.
1076 if (!strcmp(argv[i+1], "rgbg")) {
1077 user_bayer = IMAGE_BAYER_RGBG;
1078 } else if (!strcmp(argv[i+1], "bgrg")) {
1079 user_bayer = IMAGE_BAYER_BGRG;
1080 } else if (!strcmp(argv[i+1], "gbgr")) {
1081 user_bayer = IMAGE_BAYER_GRGB;
1082 } else if (!strcmp(argv[i+1], "grgb")) {
1083 user_bayer = IMAGE_BAYER_GBGR;
1084 } else if (!strcmp(argv[i+1], "none")) {
1085 user_bayer = IMAGE_BAYER_NONE;
1086 } else {
1087 bad_arg("--bayer");
1089 i++;
1090 } else if (!strcmp(argv[i], "--lpsf")) {
1091 if (i + 1 >= argc)
1092 not_enough("--lpsf");
1094 psf[psf_linear] = argv[i+1];
1095 i++;
1096 } else if (!strcmp(argv[i], "--nlpsf")) {
1097 if (i + 1 >= argc)
1098 not_enough("--nlpsf");
1100 psf[psf_nonlinear] = argv[i+1];
1101 i++;
1103 } else if (!strcmp(argv[i], "--psf-match")) {
1104 if (i + 6 >= argc)
1105 not_enough("--psf-match");
1107 psf_match = 1;
1109 for (int index = 0; index < 6; index++) {
1110 if (sscanf(argv[i + 1], "%lf", &psf_match_args[index]) != 1)
1111 bad_arg("--psf-match");
1112 i++;
1115 } else if (!strcmp(argv[i], "--device")) {
1116 if (i + 1 >= argc)
1117 not_enough("--device");
1119 device = argv[i+1];
1120 i++;
1122 #if 0
1123 } else if (!strcmp(argv[i], "--usm")) {
1125 if (d3_output != NULL)
1126 unsupported::fornow("3D modeling with unsharp mask");
1128 if (i + 1 >= argc)
1129 not_enough("--usm");
1131 sscanf(argv[i+1], "%lf", &usm_multiplier);
1132 i++;
1133 #endif
1135 } else if (!strcmp(argv[i], "--ipr")) {
1137 if (i + 1 >= argc)
1138 not_enough("--ipr");
1140 if (sscanf(argv[i+1], "%d", &ip_iterations) != 1)
1141 ui::get()->error("--ipr requires an integer argument");
1143 ui::get()->warn("--ipr is deprecated. Use --ips instead");
1144 i++;
1146 } else if (!strcmp(argv[i], "--cpp-err-median")) {
1147 d3::cpf::err_median();
1148 } else if (!strcmp(argv[i], "--cpp-err-mean")) {
1149 d3::cpf::err_mean();
1150 } else if (!strcmp(argv[i], "--vp-adjust")) {
1151 d3::align::vp_adjust();
1152 } else if (!strcmp(argv[i], "--vp-noadjust")) {
1153 d3::align::vp_noadjust();
1154 } else if (!strcmp(argv[i], "--vo-adjust")) {
1155 d3::align::vo_adjust();
1156 } else if (!strcmp(argv[i], "--vo-noadjust")) {
1157 d3::align::vo_noadjust();
1158 } else if (!strcmp(argv[i], "--ip-mean")) {
1159 ip_use_median = 0;
1160 } else if (!strcmp(argv[i], "--ip-median")) {
1161 ip_use_median = 1;
1162 } else if (!strcmp(argv[i], "--ips")) {
1164 if (i + 1 >= argc)
1165 not_enough("--ips");
1167 if (sscanf(argv[i+1], "%d", &ip_iterations) != 1)
1168 ui::get()->error("--ips requires an integer argument");
1169 i++;
1170 } else if (!strcmp(argv[i], "--ipc")) {
1171 unsupported::discontinued("--ipc <c> <i>", "--ips <i> --lpsf <c>", "--ips <i> --device <c>");
1172 } else if (!strcmp(argv[i], "--exp-extend")) {
1173 d2::image_rw::exp_scale();
1174 } else if (!strcmp(argv[i], "--exp-noextend")) {
1175 d2::image_rw::exp_noscale();
1176 } else if (!strcmp(argv[i], "--exp-register")) {
1177 exposure_register = 1;
1178 d2::align::exp_register();
1179 } else if (!strcmp(argv[i], "--exp-noregister")) {
1180 exposure_register = 0;
1181 d2::align::exp_noregister();
1182 } else if (!strcmp(argv[i], "--exp-meta-only")) {
1183 exposure_register = 2;
1184 d2::align::exp_meta_only();
1185 } else if (!strcmp(argv[i], "--drizzle-only")) {
1186 unsupported::discontinued("--drizzle-only", "--dchain box:1");
1187 } else if (!strcmp(argv[i], "--subspace-traverse")) {
1188 unsupported::undocumented("--subspace-traverse");
1189 d3::scene::set_subspace_traverse();
1190 } else if (!strcmp(argv[i], "--occ-norm")) {
1191 d3::scene::nw();
1192 } else if (!strcmp(argv[i], "--occ-nonorm")) {
1193 d3::scene::no_nw();
1194 } else if (!strcmp(argv[i], "--inc")) {
1195 inc = 1;
1196 } else if (!strcmp(argv[i], "--no-inc")) {
1197 inc = 0;
1198 } else if (!strncmp(argv[i], "--exp-mult=", strlen("--exp-mult="))) {
1199 double exp_c, exp_r, exp_b;
1200 sscanf(argv[i] + strlen("--exp-mult="), "%lf,%lf,%lf", &exp_c, &exp_r, &exp_b);
1201 exp_mult = d2::pixel(1/(exp_r * exp_c), 1/exp_c, 1/(exp_b * exp_c));
1202 } else if (!strncmp(argv[i], "--visp-scale=", strlen("--visp-scale="))) {
1204 sscanf(argv[i] + strlen("--visp-scale="), "%lf", &vise_scale_factor);
1206 if (vise_scale_factor <= 0.0)
1207 ui::get()->error("VISP scale must be greater than zero");
1209 if (!finite(vise_scale_factor))
1210 ui::get()->error("VISP scale must be finite");
1212 } else if (!strncmp(argv[i], "--scale=", strlen("--scale="))) {
1214 sscanf(argv[i] + strlen("--scale="), "%lf", &scale_factor);
1216 if (scale_factor <= 0)
1217 ui::get()->error("Scale factor must be greater than zero");
1219 if (!finite(scale_factor))
1220 ui::get()->error("Scale factor must be finite");
1222 } else if (!strncmp(argv[i], "--metric=", strlen("--metric="))) {
1223 double metric;
1224 sscanf(argv[i] + strlen("--metric="), "%lf", &metric);
1225 d2::align::set_metric_exponent(metric);
1226 } else if (!strncmp(argv[i], "--threshold=", strlen("--threshold="))) {
1227 double match_threshold;
1228 sscanf(argv[i] + strlen("--threshold="), "%lf", &match_threshold);
1229 d2::align::set_match_threshold(match_threshold);
1230 } else if (!strncmp(argv[i], "--drizzle-diam=", strlen("--drizzle-diam="))) {
1231 unsupported::discontinued("--drizzle-diam=<x>", "--dchain box:1");
1232 // sscanf(argv[i] + strlen("--drizzle-diam="), "%lf", &drizzle_radius);
1233 // drizzle_radius /= 2;
1234 } else if (!strncmp(argv[i], "--perturb-upper=", strlen("--perturb-upper="))) {
1235 double perturb_upper;
1236 int characters;
1237 sscanf(argv[i] + strlen("--perturb-upper="), "%lf%n", &perturb_upper,
1238 &characters);
1239 if (*(argv[i] + strlen("--perturb-upper=") + characters) == '%')
1240 d2::align::set_perturb_upper(perturb_upper, 1);
1241 else
1242 d2::align::set_perturb_upper(perturb_upper, 0);
1243 } else if (!strncmp(argv[i], "--perturb-lower=", strlen("--perturb-lower="))) {
1244 double perturb_lower;
1245 int characters;
1246 sscanf(argv[i] + strlen("--perturb-lower="), "%lf%n", &perturb_lower,
1247 &characters);
1248 if (perturb_lower <= 0)
1249 ui::get()->error("--perturb-lower= value is non-positive");
1251 if (*(argv[i] + strlen("--perturb-lower=") + characters) == '%')
1252 d2::align::set_perturb_lower(perturb_lower, 1);
1253 else
1254 d2::align::set_perturb_lower(perturb_lower, 0);
1255 } else if (!strncmp(argv[i], "--stepsize=", strlen("--stepsize="))) {
1256 double perturb_lower;
1257 ui::get()->warn("--stepsize is deprecated. Use --perturb-lower instead");
1258 sscanf(argv[i] + strlen("--stepsize="), "%lf", &perturb_lower);
1259 d2::align::set_perturb_lower(perturb_lower, 0);
1260 } else if (!strncmp(argv[i], "--va-upper=", strlen("--va-upper="))) {
1261 double va_upper;
1262 int characters;
1263 sscanf(argv[i] + strlen("--va-upper="), "%lf%n", &va_upper,
1264 &characters);
1265 if (*(argv[i] + strlen("--va-upper=") + characters) == '%')
1266 ui::get()->error("--va-upper= does not accept '%' arguments\n");
1267 else
1268 d3::cpf::set_va_upper(va_upper);
1269 } else if (!strncmp(argv[i], "--cpp-upper=", strlen("--cpp-upper="))) {
1270 double perturb_upper;
1271 int characters;
1272 sscanf(argv[i] + strlen("--cpp-upper="), "%lf%n", &perturb_upper,
1273 &characters);
1274 if (*(argv[i] + strlen("--cpp-upper=") + characters) == '%')
1275 ui::get()->error("--cpp-upper= does not currently accept '%' arguments\n");
1276 else
1277 d3::cpf::set_cpp_upper(perturb_upper);
1278 } else if (!strncmp(argv[i], "--cpp-lower=", strlen("--cpp-lower="))) {
1279 double perturb_lower;
1280 int characters;
1281 sscanf(argv[i] + strlen("--cpp-lower="), "%lf%n", &perturb_lower,
1282 &characters);
1283 if (*(argv[i] + strlen("--cpp-lower=") + characters) == '%')
1284 ui::get()->error("--cpp-lower= does not currently accept '%' arguments\n");
1285 else
1286 d3::cpf::set_cpp_lower(perturb_lower);
1287 } else if (!strncmp(argv[i], "--hf-enhance=", strlen("--hf-enhance="))) {
1288 unsupported::discontinued("--hf-enhance=<x>");
1289 } else if (!strncmp(argv[i], "--rot-upper=", strlen("--rot-upper="))) {
1290 double rot_max;
1291 sscanf(argv[i] + strlen("--rot-upper="), "%lf", &rot_max);
1292 d2::align::set_rot_max((int) floor(rot_max));
1293 } else if (!strncmp(argv[i], "--bda-mult=", strlen("--bda-mult="))) {
1294 double bda_mult;
1295 sscanf(argv[i] + strlen("--bda-mult="), "%lf", &bda_mult);
1296 d2::align::set_bda_mult(bda_mult);
1297 } else if (!strncmp(argv[i], "--bda-rate=", strlen("--bda-rate="))) {
1298 double bda_rate;
1299 sscanf(argv[i] + strlen("--bda-rate="), "%lf", &bda_rate);
1300 d2::align::set_bda_rate(bda_rate);
1301 } else if (!strncmp(argv[i], "--lod-max=", strlen("--lod-max="))) {
1302 double lod_max;
1303 sscanf(argv[i] + strlen("--lod-max="), "%lf", &lod_max);
1304 d2::align::set_lod_max((int) floor(lod_max));
1305 } else if (!strncmp(argv[i], "--cpf-load=", strlen("--cpf-load="))) {
1306 d3::cpf::init_loadfile(argv[i] + strlen("--cpf-load="));
1307 #if 0
1308 } else if (!strncmp(argv[i], "--model-load=", strlen("--model-load="))) {
1309 d3::scene::load_model(argv[i] + strlen("--model-load="));
1310 } else if (!strncmp(argv[i], "--model-save=", strlen("--model-save="))) {
1311 d3::scene::save_model(argv[i] + strlen("--model-save="));
1312 #endif
1313 } else if (!strncmp(argv[i], "--trans-load=", strlen("--trans-load="))) {
1314 d2::tload_delete(tload);
1315 tload = d2::tload_new(argv[i] + strlen("--trans-load="));
1316 d2::align::set_tload(tload);
1317 } else if (!strncmp(argv[i], "--trans-save=", strlen("--trans-save="))) {
1318 tsave_delete(tsave);
1319 tsave = d2::tsave_new(argv[i] + strlen("--trans-save="));
1320 d2::align::set_tsave(tsave);
1321 } else if (!strncmp(argv[i], "--3d-trans-load=", strlen("--3d-trans-load="))) {
1322 d3::tload_delete(d3_tload);
1323 d3_tload = d3::tload_new(argv[i] + strlen("--3d-trans-load="));
1324 d3::align::set_tload(d3_tload);
1325 } else if (!strncmp(argv[i], "--3d-trans-save=", strlen("--3d-trans-save="))) {
1326 d3::tsave_delete(d3_tsave);
1327 d3_tsave = d3::tsave_new(argv[i] + strlen("--3d-trans-save="));
1328 d3::align::set_tsave(d3_tsave);
1329 } else {
1332 * Trap illegal options and end-of-option indicators.
1335 if (!strcmp(argv[i], "--"))
1336 i++;
1337 else if (!strncmp(argv[i], "--", strlen("--")))
1338 ui::get()->illegal_option(argv[i]);
1341 * Apply implication logic.
1344 if (extend == 0 && vise_count != 0) {
1345 implication::changed("VISP requires increased image extents.",
1346 "Image extension is now enabled.",
1347 "--extend");
1348 extend = 1;
1351 if (psf_match && ex_count)
1352 unsupported::fornow("PSF calibration with exclusion regions.");
1355 if (d3_output != NULL && ip_iterations != 0)
1356 unsupported::fornow("3D modeling with Irani-Peleg rendering");
1358 #if 0
1359 if (extend == 0 && d3_output != NULL) {
1360 implication::changed("3D modeling requires increased image extents.",
1361 "Image extension is now enabled.",
1362 "--extend");
1363 extend = 1;
1365 #endif
1367 if (cx_parameter != 0 && !exposure_register) {
1368 implication::changed("Certainty-based rendering requires exposure registration.",
1369 "Exposure registration is now enabled.",
1370 "--exp-register");
1371 d2::align::exp_register();
1372 exposure_register = 1;
1376 * Set alignment class exclusion region static variables
1379 d2::align::set_exclusion(ex_parameters, ex_count);
1382 * Initialize renderer class statics.
1385 d2::render::render_init(ex_count, ex_parameters, ex_show, extend, scale_factor);
1388 * Set confidence
1391 d2::exposure::set_confidence(cx_parameter);
1394 * Keep transformations for Irani-Peleg, psf-match, and
1395 * VISE
1398 if (ip_iterations > 0 || psf_match || vise_count > 0) {
1399 d2::align::keep();
1403 * Initialize device-specific variables
1406 d2::psf *device_response[psf_N] = { NULL, NULL };
1407 d2::exposure **input_exposure = NULL;
1408 ale_pos view_angle = 43.7 * M_PI / 180;
1409 // ale_pos view_angle = 90 * M_PI / 180;
1410 input_exposure = (d2::exposure **)
1411 malloc((argc - i - 1) * sizeof(d2::exposure *));
1413 if (device != NULL) {
1414 if (!strcmp(device, "xvp610_640x480")) {
1415 device_response[psf_linear] = new xvp610_640x480::lpsf();
1416 device_response[psf_nonlinear] = new xvp610_640x480::nlpsf();
1417 for (int ii = 0; ii < argc - i - 1; ii++)
1418 input_exposure[ii] = new xvp610_640x480::exposure();
1419 view_angle = xvp610_640x480::view_angle();
1420 } else if (!strcmp(device, "xvp610_320x240")) {
1421 device_response[psf_linear] = new xvp610_320x240::lpsf();
1422 device_response[psf_nonlinear] = new xvp610_320x240::nlpsf();
1423 for (int ii = 0; ii < argc - i - 1; ii++)
1424 input_exposure[ii] = new xvp610_320x240::exposure();
1425 view_angle = xvp610_320x240::view_angle();
1426 } else if (!strcmp(device, "ov7620_raw_linear")) {
1427 device_response[psf_linear] = new ov7620_raw_linear::lpsf();
1428 device_response[psf_nonlinear] = NULL;
1429 for (int ii = 0; ii < argc - i - 1; ii++)
1430 input_exposure[ii] = new ov7620_raw_linear::exposure();
1431 d2::image_rw::set_default_bayer(IMAGE_BAYER_BGRG);
1432 } else if (!strcmp(device, "canon_300d_raw_linear")) {
1433 device_response[psf_linear] = new canon_300d_raw_linear::lpsf();
1434 device_response[psf_nonlinear] = NULL;
1435 for (int ii = 0; ii < argc - i - 1; ii++)
1436 input_exposure[ii] = new canon_300d_raw_linear::exposure();
1437 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1438 } else if (!strcmp(device, "canon_300d_raw_linear+85mm_1.8")) {
1439 device_response[psf_linear] = new canon_300d_raw_linear_85mm_1_8::lpsf();
1440 device_response[psf_nonlinear] = NULL;
1441 for (int ii = 0; ii < argc - i - 1; ii++)
1442 input_exposure[ii] = new canon_300d_raw_linear_85mm_1_8::exposure();
1443 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1444 view_angle = canon_300d_raw_linear_85mm_1_8::view_angle();
1445 } else if (!strcmp(device, "canon_300d_raw_linear+50mm_1.8")) {
1446 device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_8::lpsf();
1447 device_response[psf_nonlinear] = NULL;
1448 for (int ii = 0; ii < argc - i - 1; ii++)
1449 input_exposure[ii] = new canon_300d_raw_linear_50mm_1_8::exposure();
1450 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1451 view_angle = canon_300d_raw_linear_50mm_1_8::view_angle();
1452 } else if (!strcmp(device, "canon_300d_raw_linear+50mm_1.4")) {
1453 device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_4::lpsf();
1454 device_response[psf_nonlinear] = NULL;
1455 for (int ii = 0; ii < argc - i - 1; ii++)
1456 input_exposure[ii] = new canon_300d_raw_linear_50mm_1_4::exposure();
1457 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1458 view_angle = canon_300d_raw_linear_50mm_1_4::view_angle();
1459 } else if (!strcmp(device, "canon_300d_raw_linear+50mm_1.4@1.4")) {
1460 device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_4_1_4::lpsf();
1461 device_response[psf_nonlinear] = NULL;
1462 for (int ii = 0; ii < argc - i - 1; ii++)
1463 input_exposure[ii] = new canon_300d_raw_linear_50mm_1_4_1_4::exposure();
1464 d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG);
1465 view_angle = canon_300d_raw_linear_50mm_1_4_1_4::view_angle();
1466 } else {
1467 ui::get()->unknown_device(device);
1469 } else {
1470 for (int ii = 0; ii < argc - i - 1; ii++)
1471 input_exposure[ii] = new d2::exposure_default();
1475 * User-specified variables.
1478 if (user_view_angle != 0) {
1479 view_angle = user_view_angle;
1482 if (user_bayer != IMAGE_BAYER_DEFAULT) {
1483 d2::image_rw::set_default_bayer(user_bayer);
1487 * PSF-match exposure.
1489 if (psf_match) {
1490 delete input_exposure[argc - i - 2];
1491 input_exposure[argc - i - 2] = new d2::exposure_default();
1495 * Initialize output exposure
1498 d2::exposure *output_exposure = new d2::exposure_default();
1499 output_exposure->set_multiplier(exp_mult);
1502 * Configure the response function.
1505 d2::psf *response[2] = {NULL, NULL};
1507 for (int n = 0; n < psf_N; n++ ) {
1508 if (psf[n] != NULL) {
1510 response[n] = d2::psf_parse::get((n == psf_linear), psf[n]);
1512 } else if (device_response[n] != NULL) {
1515 * Device-specific response
1518 response[n] = device_response[n];
1520 } else {
1523 * Default point-spread function.
1526 if (n == psf_linear) {
1529 * Default lpsf is a box filter
1530 * of diameter 1.0 (radius
1531 * 0.5).
1534 response[n] = new d2::box(0.5);
1536 } else if (n == psf_nonlinear) {
1539 * nlpsf is disabled by default.
1542 response[n] = NULL;
1548 * First file argument. Print general file information as well
1549 * as information specific to this argument. Initialize image
1550 * file handler.
1554 * There should be at least two file arguments.
1557 if (i >= argc - 1) {
1558 hi.usage();
1559 exit(1);
1562 d2::image_rw::init(argc - i - 1, argv + i, argv[argc - 1], input_exposure, output_exposure);
1563 ochain_names[0] = argv[argc - 1];
1566 * Handle control point data for alignment
1568 d2::align::set_cp_count(d3::cpf::count());
1569 for (unsigned int ii = 0; ii < d3::cpf::count(); ii++)
1570 d2::align::set_cp(ii, d3::cpf::get_2d(ii));
1573 * PSF-match bayer patterns.
1576 if (psf_match) {
1577 d2::image_rw::set_specific_bayer(argc - i - 2, IMAGE_BAYER_NONE);
1581 * Handle alignment weight map, if necessary
1584 if (wm_filename != NULL) {
1585 d2::image *weight_map;
1586 weight_map = d2::image_rw::read_image(wm_filename, new d2::exposure_linear());
1587 weight_map->set_offset(wm_offsety, wm_offsetx);
1588 d2::align::set_weight_map(weight_map);
1592 * Write comment information about original frame and
1593 * target image to the transformation save file, if we
1594 * have one.
1597 const d2::image *im = d2::image_rw::open(0);
1598 tsave_orig(tsave, argv[i], im->avg_channel_magnitude());
1599 tsave_target(tsave, argv[argc - 1]);
1600 d2::image_rw::close(0);
1603 * Initialize alignment interpolant.
1606 if (afilter_type != "internal")
1607 d2::align::set_interpolant(d2::render_parse::get_SSF(afilter_type));
1610 * Initialize achain and ochain.
1613 achain = d2::render_parse::get(achain_type);
1615 for (int chain = 0; chain < oc_count; chain++)
1616 ochain[chain] = d2::render_parse::get(ochain_types[chain]);
1619 * Use merged renderings as reference images in
1620 * alignment.
1623 d2::align::set_reference(achain);
1626 * Tell the alignment class about the scale factor.
1629 d2::align::set_scale(scale_factor);
1632 * Initialize visp.
1635 d2::vise_core::set_scale(vise_scale_factor);
1637 for (int opt = 0; opt < vise_count; opt++) {
1638 d2::vise_core::add(d2::render_parse::get(visp[opt * 4 + 0]),
1639 visp[opt * 4 + 1],
1640 visp[opt * 4 + 2],
1641 visp[opt * 4 + 3]);
1645 * Initialize non-incremental renderers
1648 #if 0
1649 if (usm_multiplier != 0) {
1652 * Unsharp Mask renderer
1655 ochain[0] = new d2::usm(ochain[0], scale_factor,
1656 usm_multiplier, inc, response[psf_linear],
1657 response[psf_nonlinear], &input_exposure[0]);
1659 #endif
1661 if (psf_match) {
1664 * Point-spread function calibration renderer.
1665 * This renderer does not produce image output.
1666 * It is reserved for use with the point-spread
1667 * function calibration script
1668 * ale-psf-calibrate.
1671 ochain[0] = new d2::psf_calibrate(ochain[0],
1672 1, inc, response[psf_linear],
1673 response[psf_nonlinear],
1674 psf_match_args);
1676 } else if (ip_iterations != 0) {
1679 * Irani-Peleg renderer
1682 ochain[0] = new d2::ipc( ochain[0], ip_iterations,
1683 inc, response[psf_linear],
1684 response[psf_nonlinear],
1685 (exposure_register == 1), ip_use_median);
1689 * Handle the original frame.
1692 ui::get()->original_frame_start(argv[i]);
1694 for (int opt = 0; opt < oc_count; opt++) {
1695 ui::get()->set_orender_current(opt);
1696 ochain[opt]->sync(0);
1697 if (inc) {
1698 ui::get()->writing_output(opt);
1699 d2::image_rw::write_image(ochain_names[opt],
1700 ochain[opt]->get_image(0));
1704 d2::vise_core::frame_queue_add(0);
1706 ui::get()->original_frame_done();
1709 * Handle supplemental frames.
1712 for (unsigned int j = 1; j < d2::image_rw::count(); j++) {
1714 const char *name = d2::image_rw::name(j);
1716 ui::get()->supplemental_frame_start(name);
1719 * Write comment information about the
1720 * supplemental frame to the transformation
1721 * save file, if we have one.
1724 tsave_info (tsave, name);
1726 const d2::image *im = d2::image_rw::open(j);
1727 d2::pixel apm = im->avg_channel_magnitude();
1728 tsave_apm(tsave, apm[0], apm[1], apm[2]);
1729 d2::image_rw::close(j);
1731 for (int opt = 0; opt < oc_count; opt++) {
1732 ui::get()->set_orender_current(opt);
1733 ochain[opt]->sync(j);
1734 if (inc) {
1735 ui::get()->writing_output(opt);
1736 d2::image_rw::write_image(ochain_names[opt],
1737 ochain[opt]->get_image(j));
1741 d2::vise_core::frame_queue_add(j);
1743 ui::get()->supplemental_frame_done();
1747 * Do any post-processing and output final image
1749 * XXX: note that non-incremental renderers currently
1750 * return zero for ochain[0]->sync(), since they write
1751 * output internally when inc != 0.
1754 for (int opt = 0; opt < oc_count; opt++)
1755 if ((ochain[opt]->sync() || !inc) && !psf_match)
1756 d2::image_rw::write_image(ochain_names[opt], ochain[opt]->get_image());
1759 * Output a summary match statistic.
1762 ui::get()->ale_done((double) d2::align::match_summary());
1765 * Perform any 3D tasks
1768 optimizations::begin_3d_work();
1770 if (d3_count > 0) {
1772 d3::align::init_angle(view_angle);
1774 d3::align::init_from_d2();
1776 if (d3::cpf::count() > 0) {
1777 d3::cpf::solve_3d();
1780 d3::align::write_alignments();
1782 d3::scene::init_from_d2();
1784 // d3::scene::add_control_points();
1786 // d3::scene::relax_triangle_model();
1788 d3::scene::make_space(d3_depth, d3_output, &d3_depth_pt, &d3_output_pt);
1790 // fprintf(stderr, "Total pixels: %lu\n", d3::scene::total_pixels);
1791 // fprintf(stderr, "Total ambiguity: %lu\n", d3::scene::total_ambiguity);
1792 // fprintf(stderr, "Total tsteps: %lu\n", d3::scene::total_tsteps);
1793 // fprintf(stderr, "Total divisions: %lu\n", d3::scene::total_divisions);
1795 fprintf(stderr, "Updating occupancy values");
1796 d3::scene::reduce_cost_to_search_depth(output_exposure, inc);
1797 fprintf(stderr, ".\n");
1799 fprintf(stderr, "Writing 3D output");
1800 d3::scene::d3px(d3px_count, d3px_parameters);
1801 for (unsigned int i = 0; i < d2::image_rw::count(); i++) {
1802 assert (i < d3_count);
1804 if (d3_depth[i] != NULL) {
1805 const d2::image *im = d3::scene::depth(i);
1806 d2::image_rw::write_image(d3_depth[i], im, output_exposure, 1, 1);
1807 delete im;
1810 if (d3_output[i] != NULL) {
1811 const d2::image *im = d3::scene::view(i);
1812 d2::image_rw::write_image(d3_output[i], im, output_exposure);
1813 delete im;
1816 for (std::map<const char *, d3::pt>::iterator i = d3_output_pt.begin();
1817 i != d3_output_pt.end(); i++) {
1819 const d2::image *im = d3::scene::view(i->second);
1820 d2::image_rw::write_image(i->first, im, output_exposure);
1821 delete im;
1824 for (std::map<const char *, d3::pt>::iterator i = d3_depth_pt.begin();
1825 i != d3_depth_pt.end(); i++) {
1827 const d2::image *im = d3::scene::depth(i->second);
1828 d2::image_rw::write_image(i->first, im, output_exposure, 1, 1);
1829 delete im;
1832 fprintf(stderr, ".\n");
1834 for (unsigned int i = d2::image_rw::count(); i < d3_count; i++) {
1835 if (d3_depth[i] != NULL) {
1836 fprintf(stderr, "\n\n*** Frame number for --3dd too high. ***\n\n");
1838 if (d3_output[i] != NULL) {
1839 fprintf(stderr, "\n\n*** Frame number for --3dv too high. ***\n\n");
1845 * Destroy the image file handler
1848 d2::image_rw::destroy();
1851 * Delete the transformation file structures, if any
1852 * exist.
1855 tsave_delete(tsave);
1856 tload_delete(tload);
1859 * We're done.
1862 exit(0);
1867 * If there was no output, the user might need more information.
1870 hi.usage();
1871 exit(1);