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.
38 #include "../ale_pos.h"
39 #include "../ale_real.h"
46 #include "unsupported.h"
47 #include "implication.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"
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
))
90 else if (!strcmp(argv
[i
], "--"))
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
)))
106 else if (!strcmp(argv
[i
], "--"))
113 * Reallocation function
115 void *local_realloc(void *ptr
, size_t size
) {
116 void *new_ptr
= realloc(ptr
, size
);
119 ui::get()->memory_error_location("main()");
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
);
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.
150 static std::stack
<environment
*> environment_stack
;
151 static std::set
<environment
*> environment_set
;
153 std::map
<const char *, const char *> environment_map
;
156 const char *get(const char *name
) {
157 if (environment_map
.count(name
) == 0)
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
);
174 ui::get()->memory_error_location("environment::set_ptr");
176 int count
= snprintf(c
, chars
, "%p", pointer
);
178 assert (count
>= 0 && count
< chars
);
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
;
192 environment_set
.insert(s
);
196 static environment
*get_env(const char *name
) {
198 sscanf(name
, "%p", &ptr_value
);
201 * Check for bad pointers.
204 if (!environment_set
.count((environment
*) ptr_value
)) {
206 fprintf(stderr
, "Bad environment pointer.\n");
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();
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
);
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.
259 virtual char *get() = 0;
261 virtual ~token_reader() {
265 class cli_token_reader
{
271 cli_token_reader(int c
, const char *v
[]) {
278 return argv
[arg_index
++];
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")) {
313 fprintf(stdout
, "%s", version
);
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"));
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
)
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("--"))
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
;
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");
392 d2::image
*i
= new d2::image_ale_real((int)h
, (int)w
, 3);
393 d2::transformation t
= d2::transformation::gpt_identity(i
, 1);
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]);
416 * Flags and variables
419 double scale_factor
= 1;
420 double vise_scale_factor
= 1;
422 double usm_multiplier
= 0.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
;
435 double psf_match_args
[6];
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
;
443 int *ex_parameters
= NULL
;
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
;
454 const char **visp
= NULL
;
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";
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";
492 d2::image_rw::exp_noscale();
494 } else if (arg_count(argc
, argv
, "--qn")) {
495 ochain_types
[0] = "sinc*lanc:6";
496 achain_type
= "sinc*lanc:6";
499 d2::image_rw::exp_noscale();
501 } else if (arg_count(argc
, argv
, "--q1")) {
502 ochain_types
[0] = "median:fine:sinc*lanc:8,triangle:2";
503 achain_type
= "triangle:2";
506 d2::image_rw::exp_noscale();
508 } else if (arg_count(argc
, argv
, "--q2")) {
509 ochain_types
[0] = "sinc*lanc:8";
510 achain_type
= "sinc*lanc:8";
513 d2::image_rw::exp_noscale();
515 } else if (arg_count(argc
, argv
, "--qr")) {
516 ochain_types
[0] = "sinc*lanc:8";
517 achain_type
= "sinc*lanc:8";
520 d2::image_rw::exp_scale();
526 ochain_types
[0] = "fine:box:1,triangle:2";
527 achain_type
= "triangle:2";
530 d2::image_rw::exp_noscale();
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")) {
569 } else if (!strcmp(argv
[i
], "--align-green")) {
571 } else if (!strcmp(argv
[i
], "--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")) {
593 } else if (!strcmp(argv
[i
], "--extend")) {
595 } else if (!strcmp(argv
[i
], "--no-mc")) {
597 } else if (!strcmp(argv
[i
], "--oc")) {
599 } else if (!strcmp(argv
[i
], "--no-oc")) {
601 } else if (!strcmp(argv
[i
], "--gs")) {
605 d2::align::gs(argv
[i
+1]);
608 } else if (!strcmp(argv
[i
], "--gs-mo")) {
610 not_enough("--gs-mo");
612 unsigned int mo_parameter
;
613 if (sscanf(argv
[i
+1], "%u", &mo_parameter
) != 1)
616 d2::align::gs_mo(mo_parameter
);
619 } else if (!strcmp(argv
[i
], "--focus")) {
622 * Check for argument availability
630 double inf
= one
/ zero
;
632 assert (isinf(inf
) == +1);
638 unsigned int type
= 0;
642 if (!strcmp(argv
[i
+1], "d")) {
647 not_enough("--focus d");
649 if (sscanf(argv
[i
+2], "%lf", &distance
) != 1)
650 bad_arg("--focus d");
654 } else if (!strcmp(argv
[i
+1], "p")) {
659 not_enough("--focus");
661 if (sscanf(argv
[i
+2], "%lf", &px
) != 1
662 || sscanf(argv
[i
+3], "%lf", &py
) != 1)
694 while (options
&& i
< argc
) {
695 if (!strncmp(argv
[i
], "ci=", 3)) {
696 if(sscanf(argv
[i
] + 3, "%u", &ci
) != 1)
698 } else if (!strncmp(argv
[i
], "fr=", 3)) {
699 if(sscanf(argv
[i
] + 3, "%lf", &fr
) != 1)
701 } else if (!strncmp(argv
[i
], "ht=", 3)) {
702 if(sscanf(argv
[i
] + 3, "%lf", &ht
) != 1)
704 } else if (!strncmp(argv
[i
], "vt=", 3)) {
705 if(sscanf(argv
[i
] + 3, "%lf", &vt
) != 1)
707 } else if (!strncmp(argv
[i
], "sy=", 3)) {
708 if(sscanf(argv
[i
] + 3, "%lf", &sy
) != 1)
710 } else if (!strncmp(argv
[i
], "ey=", 3)) {
711 if(sscanf(argv
[i
] + 3, "%lf", &ey
) != 1)
713 } else if (!strncmp(argv
[i
], "sx=", 3)) {
714 if(sscanf(argv
[i
] + 3, "%lf", &sx
) != 1)
716 } else if (!strncmp(argv
[i
], "ex=", 3)) {
717 if(sscanf(argv
[i
] + 3, "%lf", &ex
) != 1)
719 } else if (!strncmp(argv
[i
], "sd=", 3)) {
720 if(sscanf(argv
[i
] + 3, "%lf", &sd
) != 1)
722 } else if (!strncmp(argv
[i
], "ed=", 3)) {
723 if(sscanf(argv
[i
] + 3, "%lf", &ed
) != 1)
725 } else if (!strncmp(argv
[i
], "ap=", 3)) {
726 if(sscanf(argv
[i
] + 3, "%lf", &ap
) != 1)
728 } else if (!strncmp(argv
[i
], "sc=", 3)) {
729 if(sscanf(argv
[i
] + 3, "%u", &sc
) != 1)
731 } else if (!strncmp(argv
[i
], "sr=", 3)) {
732 if (!strcmp(argv
[i
], "sr=aperture")) {
734 } else if (!strcmp(argv
[i
], "sr=pixel")) {
739 } else if (!strncmp(argv
[i
], "fs=", 3)) {
740 if (!strcmp(argv
[i
], "fs=mean")) {
742 } else if (!strcmp(argv
[i
], "fs=median")) {
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")) {
761 * Unsupported configurations
765 unsupported::fornow("3D modeling with Irani-Peleg rendering");
769 unsupported::fornow("3D modeling with unsharp mask");
773 * Check for argument availability
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
;
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)
809 view_angle
*= 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
;
828 } else if (!strcmp(argv
[i
], "--3dv")) {
831 unsigned int frame_no
;
834 * Unsupported configurations
838 unsupported::fornow("3D modeling with Irani-Peleg rendering");
842 unsupported::fornow("3D modeling with unsharp mask");
846 * Check for argument availability
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];
875 } else if (!strcmp(argv
[i
], "--3dd")) {
878 unsigned int frame_no
;
881 * Unsupported configurations
885 unsupported::fornow("3D modeling with Irani-Peleg rendering");
889 unsupported::fornow("3D modeling with unsharp mask");
893 * Check for argument availability
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];
923 } else if (!strcmp(argv
[i
], "--view-angle")) {
925 not_enough("--view-angle");
928 sscanf(argv
[i
+1], "%lf", &va_parameter
);
930 user_view_angle
= va_parameter
* M_PI
/ 180;
931 } else if (!strcmp(argv
[i
], "--cpf-load")) {
933 not_enough("--cpf-load");
935 d3::cpf::init_loadfile(argv
[i
+1]);
937 } else if (!strcmp(argv
[i
], "--ui=stream")) {
939 } else if (!strcmp(argv
[i
], "--ui=tty")) {
941 } else if (!strcmp(argv
[i
], "--3d-fmr")) {
944 not_enough("--3d-fmr");
946 double fmr_parameter
;
947 sscanf(argv
[i
+1], "%lf", &fmr_parameter
);
949 d3::scene::fmr(fmr_parameter
);
951 } else if (!strcmp(argv
[i
], "--3d-dmr")) {
954 not_enough("--3d-dmr");
956 double dmr_parameter
;
957 sscanf(argv
[i
+1], "%lf", &dmr_parameter
);
959 d3::scene::dmr(dmr_parameter
);
961 } else if (!strcmp(argv
[i
], "--et")) {
967 sscanf(argv
[i
+1], "%lf", &et_parameter
);
969 d3::scene::et(et_parameter
);
971 } else if (!strcmp(argv
[i
], "--st")) {
976 sscanf(argv
[i
+1], "%lf", &st_parameter
);
978 d3::cpf::st(st_parameter
);
979 } else if (!strcmp(argv
[i
], "--di-lower")) {
981 not_enough("--di-lower");
984 sscanf(argv
[i
+1], "%lf", &di_parameter
);
986 d3::scene::di_lower(di_parameter
);
987 } else if (!strcmp(argv
[i
], "--rc")) {
992 sscanf(argv
[i
+1], "%lf", &rc_parameter
);
994 d3::scene::rc(rc_parameter
);
995 } else if (!strcmp(argv
[i
], "--do-try")) {
997 not_enough("--do-try");
1000 sscanf(argv
[i
+1], "%lf", &do_parameter
);
1002 d3::scene::do_try(do_parameter
);
1003 } else if (!strcmp(argv
[i
], "--di-upper")) {
1005 not_enough("--di-upper");
1007 double dgi_parameter
;
1008 sscanf(argv
[i
+1], "%lf", &dgi_parameter
);
1010 d3::scene::di_upper(dgi_parameter
);
1011 } else if (!strcmp(argv
[i
], "--fc")) {
1015 double fc_parameter
;
1016 sscanf(argv
[i
+1], "%lf", &fc_parameter
);
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")) {
1025 not_enough("--def-nn");
1027 double nn_parameter
;
1028 sscanf(argv
[i
+1], "%lf", &nn_parameter
);
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")) {
1041 double mc_parameter
;
1042 sscanf(argv
[i
+1], "%lf", &mc_parameter
);
1043 mc_parameter
/= 100;
1045 d2::align::mc(mc_parameter
);
1047 } else if (!strcmp(argv
[i
], "--fx")) {
1052 double fx_parameter
;
1053 sscanf(argv
[i
+1], "%lf", &fx_parameter
);
1055 d3::scene::fx(fx_parameter
);
1057 } else if (!strcmp(argv
[i
], "--tcem")) {
1060 not_enough("--tcem");
1062 double tcem_parameter
;
1063 sscanf(argv
[i
+1], "%lf", &tcem_parameter
);
1065 d3::scene::tcem(tcem_parameter
);
1067 } else if (!strcmp(argv
[i
], "--oui")) {
1070 not_enough("--oui");
1072 unsigned int oui_parameter
;
1073 sscanf(argv
[i
+1], "%u", &oui_parameter
);
1075 d3::scene::oui(oui_parameter
);
1077 } else if (!strcmp(argv
[i
], "--pa")) {
1082 unsigned int pa_parameter
;
1083 sscanf(argv
[i
+1], "%u", &pa_parameter
);
1085 d3::scene::pa(pa_parameter
);
1087 } else if (!strcmp(argv
[i
], "--pc")) {
1092 d3::scene::pc(argv
[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");
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");
1115 } else if (!strcmp(argv
[i
], "--fl")) {
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");
1127 d2::align::set_frequency_cut(h
, v
, a
);
1129 ui::get()->error_hint("--fl is not supported", "rebuild ALE with FFTW=1");
1131 } else if (!strcmp(argv
[i
], "--wmx")) {
1133 not_enough("--wmx");
1135 d2::align::set_wmx(argv
[i
+1], argv
[i
+2], argv
[i
+3]);
1137 ui::get()->error_hint("--wmx is not supported", "rebuild ALE with POSIX=1");
1140 } else if (!strcmp(argv
[i
], "--flshow")) {
1142 not_enough("--flshow");
1143 d2::align::set_fl_show(argv
[i
+1]);
1145 } else if (!strcmp(argv
[i
], "--3dpx")) {
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)
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
1172 } else if (!strcmp(argv
[i
], "--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)
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
1199 } else if (!strcmp(argv
[i
], "--crop")) {
1201 not_enough("--crop");
1203 ex_parameters
= (int *) local_realloc(ex_parameters
, (ex_count
+ 4) * 6 * sizeof(int));
1206 for (int param
= 0; param
< 6; param
++)
1207 if (sscanf(argv
[i
+ param
+ 1], "%d", &(crop_args
[param
])) != 1)
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
1266 } else if (!strcmp(argv
[i
], "--exshow")) {
1268 } else if (!strcmp(argv
[i
], "--wt")) {
1274 if (sscanf(argv
[i
+ 1], "%lf", &wt
) != 1)
1277 d2::render::set_wt(wt
);
1279 } else if (!strcmp(argv
[i
], "--3d-chain")) {
1281 not_enough("--3d-chain");
1282 d3chain_type
= argv
[i
+1];
1284 } else if (!strcmp(argv
[i
], "--dchain")) {
1286 not_enough("--dchain");
1287 ochain_types
[0] = argv
[i
+1];
1289 } else if (!strcmp(argv
[i
], "--achain")) {
1291 not_enough("--achain");
1292 achain_type
= argv
[i
+1];
1294 } else if (!strcmp(argv
[i
], "--afilter")) {
1296 not_enough("--afilter");
1297 afilter_type
= argv
[i
+1];
1299 } else if (!strcmp(argv
[i
], "--ochain")) {
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];
1315 } else if (!strcmp(argv
[i
], "--visp")) {
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
];
1327 } else if (!strcmp(argv
[i
], "--cx")) {
1332 sscanf(argv
[i
+1], "%lf", &cx_parameter
);
1335 } else if (!strcmp(argv
[i
], "--no-cx")) {
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")) {
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
;
1362 } else if (!strcmp(argv
[i
], "--lpsf")) {
1364 not_enough("--lpsf");
1366 psf
[psf_linear
] = argv
[i
+1];
1368 } else if (!strcmp(argv
[i
], "--nlpsf")) {
1370 not_enough("--nlpsf");
1372 psf
[psf_nonlinear
] = argv
[i
+1];
1375 } else if (!strcmp(argv
[i
], "--psf-match")) {
1377 not_enough("--psf-match");
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");
1387 } else if (!strcmp(argv
[i
], "--device")) {
1389 not_enough("--device");
1395 } else if (!strcmp(argv
[i
], "--usm")) {
1397 if (d3_output
!= NULL
)
1398 unsupported::fornow("3D modeling with unsharp mask");
1401 not_enough("--usm");
1403 sscanf(argv
[i
+1], "%lf", &usm_multiplier
);
1407 } else if (!strcmp(argv
[i
], "--ipr")) {
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");
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")) {
1432 } else if (!strcmp(argv
[i
], "--ip-median")) {
1434 } else if (!strcmp(argv
[i
], "--ips")) {
1437 not_enough("--ips");
1439 if (sscanf(argv
[i
+1], "%d", &ip_iterations
) != 1)
1440 ui::get()->error("--ips requires an integer argument");
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")) {
1468 } else if (!strcmp(argv
[i
], "--occ-nonorm")) {
1470 } else if (!strcmp(argv
[i
], "--inc")) {
1472 } else if (!strcmp(argv
[i
], "--no-inc")) {
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="))) {
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
;
1513 sscanf(argv
[i
] + strlen("--perturb-upper="), "%lf%n", &perturb_upper
,
1515 if (*(argv
[i
] + strlen("--perturb-upper=") + characters
) == '%')
1516 d2::align::set_perturb_upper(perturb_upper
, 1);
1518 d2::align::set_perturb_upper(perturb_upper
, 0);
1519 } else if (!strncmp(argv
[i
], "--perturb-lower=", strlen("--perturb-lower="))) {
1520 double perturb_lower
;
1522 sscanf(argv
[i
] + strlen("--perturb-lower="), "%lf%n", &perturb_lower
,
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);
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="))) {
1539 sscanf(argv
[i
] + strlen("--va-upper="), "%lf%n", &va_upper
,
1541 if (*(argv
[i
] + strlen("--va-upper=") + characters
) == '%')
1542 ui::get()->error("--va-upper= does not accept '%' arguments\n");
1544 d3::cpf::set_va_upper(va_upper
);
1545 } else if (!strncmp(argv
[i
], "--cpp-upper=", strlen("--cpp-upper="))) {
1546 double perturb_upper
;
1548 sscanf(argv
[i
] + strlen("--cpp-upper="), "%lf%n", &perturb_upper
,
1550 if (*(argv
[i
] + strlen("--cpp-upper=") + characters
) == '%')
1551 ui::get()->error("--cpp-upper= does not currently accept '%' arguments\n");
1553 d3::cpf::set_cpp_upper(perturb_upper
);
1554 } else if (!strncmp(argv
[i
], "--cpp-lower=", strlen("--cpp-lower="))) {
1555 double perturb_lower
;
1557 sscanf(argv
[i
] + strlen("--cpp-lower="), "%lf%n", &perturb_lower
,
1559 if (*(argv
[i
] + strlen("--cpp-lower=") + characters
) == '%')
1560 ui::get()->error("--cpp-lower= does not currently accept '%' arguments\n");
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="))) {
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="))) {
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="))) {
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="))) {
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="));
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="));
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
);
1608 * Trap illegal options and end-of-option indicators.
1611 if (!strcmp(argv
[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.",
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");
1635 if (extend
== 0 && d3_output
!= NULL
) {
1636 implication::changed("3D modeling requires increased image extents.",
1637 "Image extension is now enabled.",
1643 if (cx_parameter
!= 0 && !exposure_register
) {
1644 implication::changed("Certainty-based rendering requires exposure registration.",
1645 "Exposure registration is now enabled.",
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
);
1667 d2::exposure::set_confidence(cx_parameter
);
1670 * Keep transformations for Irani-Peleg, psf-match, and
1674 if (ip_iterations
> 0 || psf_match
|| vise_count
> 0) {
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();
1743 ui::get()->unknown_device(device
);
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.
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
];
1799 * Default point-spread function.
1802 if (n
== psf_linear
) {
1805 * Default lpsf is a box filter
1806 * of diameter 1.0 (radius
1810 response
[n
] = new d2::box(0.5);
1812 } else if (n
== psf_nonlinear
) {
1815 * nlpsf is disabled by default.
1824 * First file argument. Print general file information as well
1825 * as information specific to this argument. Initialize image
1830 * There should be at least two file arguments.
1833 if (i
>= argc
- 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.
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
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
1899 d2::align::set_reference(achain
);
1902 * Tell the alignment class about the scale factor.
1905 d2::align::set_scale(scale_factor
);
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]),
1921 * Initialize non-incremental renderers
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]);
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
],
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);
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
);
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();
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
);
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);
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
);
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
);
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);
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
2145 tsave_delete(tsave
);
2146 tload_delete(tload
);
2157 * If there was no output, the user might need more information.