// Copyright 2002, 2003, 2004, 2005, 2006 David Hilvert , // /* This file is part of the Anti-Lamenessing Engine. The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. The Anti-Lamenessing Engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the Anti-Lamenessing Engine; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __input_h__ #define __input_h__ /* * ANSI C and POSIX include files. */ #include #include #include #include #include // #include #include #include #include "../ale_math.h" /* * Interface files */ #include "ui.h" #include "unsupported.h" #include "implication.h" /* * Configuration */ #if HAVE_CONFIG_H # include #endif /* * GNU extensions */ extern "C" { #include "string.h" } /* * Types */ #include "../ale_pos.h" #include "../ale_real.h" /* * 2D include files */ #include "../d2.h" /* * 3D include files */ #include "../d3.h" /* * Thread include files */ #include "../thread.h" /* * Device configuration files */ #include "../device/xvp610_320x240.h" #include "../device/xvp610_640x480.h" #include "../device/ov7620_raw_linear.h" #include "../device/canon_300d_raw_linear.h" #include "../device/canon_300d_raw_linear_85mm_1_8.h" #include "../device/canon_300d_raw_linear_50mm_1_8.h" #include "../device/canon_300d_raw_linear_50mm_1_4.h" #include "../device/canon_300d_raw_linear_50mm_1_4_1_4.h" #include "../device/nikon_d50.h" /* * Help files */ #include "help.h" class input { /* * Flag for global options. */ static int global_options; /* * Helper functions. */ /* * Argument counter. * * Counts instances of a given option. */ static unsigned int arg_count(int argc, const char *argv[], const char *arg) { unsigned int count = 0; for (int i = 0; i < argc; i++) { if (!strcmp(argv[i], arg)) count++; else if (!strcmp(argv[i], "--")) return count; } return count; } /* * Argument prefix counter. * * Counts instances of a given option prefix. */ static unsigned int arg_prefix_count(int argc, const char *argv[], const char *pfix) { unsigned int count = 0; for (int i = 0; i < argc; i++) { if (!strncmp(argv[i], pfix, strlen(pfix))) count++; else if (!strcmp(argv[i], "--")) return count; } return count; } /* * Reallocation function */ static void *local_realloc(void *ptr, size_t size) { void *new_ptr = realloc(ptr, size); if (new_ptr == NULL) ui::get()->memory_error_location("main()"); return new_ptr; } /* * Not enough arguments function. */ static void not_enough(const char *opt_name) { ui::get()->cli_not_enough(opt_name); } /* * Bad argument function */ static void bad_arg(const char *opt_name) { ui::get()->cli_bad_arg(opt_name); } /* * String comparison class. */ class compare_strings { public: int operator()(const char *A, const char *B) const { return strcmp(A, B) < 0; } }; /* * Environment structures. * * XXX: It's arguable that these should be public members of the * 'input' class in order to allow passing environment values to other * classes, but, since we're currently using them only to prepare state * for an internal 'input' function, they can stay private for now. A * more nuanced approach will likely be required later. */ class environment { static std::stack environment_stack; static std::set environment_set; std::map environment_map; /* * Internal set operations do not protect any data. */ void internal_set(const char *name, const char *value) { environment_map[name] = value; } void internal_unset(const char *name) { environment_map.erase(name); } const char *internal_convert_pointer(const void *pointer) { int chars = sizeof(void *) * 2 + 3; char *c = (char *) malloc(sizeof(char) * chars); assert(c); if (!c) ui::get()->memory_error_location("environment::set_ptr"); int count = snprintf(c, chars, "%p", pointer); assert (count >= 0 && count < chars); return c; } void internal_set_ptr(const char *name, const void *pointer) { internal_set(name, internal_convert_pointer(pointer)); } /* * Check for restricted names. */ int name_ok(const char *name) { if (!strcmp(name, "---chain") || !strcmp(name, "---this")) return 0; return 1; } void name_check(const char *name) { if (!name_ok(name)) { fprintf(stderr, "Bad set operation."); assert(0); exit(1); } } public: /* * Get the environment map. */ std::map &get_map() { return environment_map; } /* * Public set operations restrict valid names. */ void set(const char *name, const char *value) { name_check(name); internal_set(name, value); } void unset(const char *name) { name_check(name); internal_unset(name); } void set_ptr(const char *name, const void *pointer) { name_check(name); internal_set_ptr(name, pointer); } const char *get(const char *name) { if (environment_map.count(name) == 0) return NULL; return environment_map[name]; } /* * Make an environment substructure. Note that since deep * structures are currently referenced rather than copied when * the stack is pushed, there is no current need for any * chaining mechanism. */ void make_substructure(const char *name) { environment *s = new environment; set_ptr(name, s); environment_set.insert(s); } static int is_env(const char *name) { void *ptr_value; sscanf(name, "%p", &ptr_value); /* * Check for bad pointers. */ if (!environment_set.count((environment *) ptr_value)) { return 0; } return 1; } const char *get_option_name(const char *name) { if (strncmp(name, "0 ", strlen("0 "))) return NULL; name += strlen("0 "); if (!isdigit(name[0])) return NULL; while (isdigit(name[0])) name++; if (!isspace(name[0])) return NULL; while (isspace(name[0])) name++; if (!isalnum(name[0])) return NULL; return name; } int is_option(const char *name) { return (get_option_name(name) != NULL); } int is_arg(const char *name, unsigned int arg) { assert (is_option(name)); int length = strlen(name) + 3 * sizeof(unsigned int); char *desired_string = (char *) malloc(sizeof(char) * length); snprintf(desired_string, length, "%u %s", arg, name + strlen("0 ")); int result = environment_map.count(desired_string); free(desired_string); return result > 0; } void remove_arg(const char *name, unsigned int arg) { assert (is_option(name)); assert (is_arg(name, arg)); int length = strlen(name) + 3 * sizeof(unsigned int); char *desired_string = (char *) malloc(sizeof(char) * length); snprintf(desired_string, length, "%u %s", arg, name + strlen("0 ")); environment_map.erase(desired_string); free(desired_string); } const char *get_string_arg(const char *name, unsigned int arg) { assert (is_option(name)); int length = strlen(name) + 3 * sizeof(unsigned int); char *desired_string = (char *) malloc(sizeof(char) * length); snprintf(desired_string, length, "%u %s", arg, name + strlen("0 ")); const char *result = environment_map[desired_string]; assert (result); free(desired_string); return result; } long int get_long_arg(const char *name, unsigned int arg) { assert (is_option(name)); const char *string = get_string_arg(name, arg); char *endptr; long int result = strtol(string, &endptr, 0); if (endptr[0] != '\0') { fprintf(stderr, "\n\nError: bad argument in `%s'.\n\n", get_option_name(name)); exit(1); } return result; } int get_int_arg(const char *name, unsigned int arg) { return (int) get_long_arg(name, arg); } unsigned int get_unsigned_arg(const char *name, unsigned int arg) { long int result = get_long_arg(name, arg); if (result < 0) { fprintf(stderr, "\n\nError: bad argument in `%s'.\n\n", get_option_name(name)); exit(1); } return (unsigned int) result; } double get_double_arg(const char *name, unsigned int arg) { assert (is_option(name)); const char *string = get_string_arg(name, arg); char *endptr; double result = strtod(string, &endptr); if (endptr[0] != '\0') { fprintf(stderr, "\n\nError: bad argument in `%s'.\n\n", get_option_name(name)); exit(1); } return result; } static environment *get_env(const char *name) { assert(name); void *ptr_value; sscanf(name, "%p", &ptr_value); /* * Check for bad pointers. */ if (!environment_set.count((environment *) ptr_value)) { assert(0); fprintf(stderr, "Bad environment pointer.\n"); exit(1); } return (environment *) ptr_value; } /* * Prepend to a list. */ void prepend(const char *list, const char *element) { environment *d = get_env(get(list)); make_substructure(list); get_env(get(list))->set("a", element); get_env(get(list))->set_ptr("d", d); } void prepend_ptr(const char *list, void *ptr) { prepend(list, internal_convert_pointer(ptr)); } /* * Clone the environment. */ environment *clone() { environment *e = new environment(); for (std::map::iterator i = environment_map.begin(); i != environment_map.end(); i++) { if (!name_ok(i->first)) continue; if (is_env(i->second)) { e->set_ptr(i->first, get_env(i->second)->clone()); } else { e->set(i->first, i->second); } } return e; } static environment *top() { if (environment_stack.empty()) { environment_stack.push(new environment); environment_set.insert(environment_stack.top()); } return environment_stack.top(); } static void push() { environment *e = new environment; e->environment_map = environment_stack.top()->environment_map; e->internal_set_ptr("---chain", environment_stack.top()); e->internal_set_ptr("---this", e); e->make_substructure("---dup"); environment_stack.push(e); environment_set.insert(e); } static void dup_second() { environment_stack.top()->prepend_ptr("---dup", environment::get_env(environment_stack.top()->get("---chain"))); } static void push_and_dup_output() { push(); dup_second(); } static void pop() { assert(!environment_stack.empty()); /* * Execution environments should never be referenced by * structures further up the call chain, so they can * safely be deleted. (XXX: In particular, while * lexical scoping may require copying of execution * environments from lower on the call chain, there is * no obvious reason that a reference should be used in * this case; a shallow copy should be used instead.) */ environment_set.erase(environment_stack.top()); delete environment_stack.top(); environment_stack.pop(); } /* * Set with duplication. */ void set_with_dup(const char *name, const char *value) { set(name, value); if (!get("---dup")) return; environment *dup_item = get_env(get("---dup")); assert (dup_item); while (dup_item->get("a")) { get_env(dup_item->get("a"))->set_with_dup(name, value); assert(dup_item->get("d")); dup_item = get_env(dup_item->get("d")); assert(dup_item); } } }; /* * Read tokens from a stream. */ class token_reader { public: /* * Get the next token */ virtual const char *get() = 0; /* * Peek at the next token. */ virtual const char *peek() = 0; /* * Divert the stream until the next occurrence of TOKEN. */ virtual token_reader *divert(const char *open_token, const char *close_token) = 0; virtual int expects_exactly_one_option(void) { return 0; } virtual ~token_reader() { } }; class argument_parsing_token_reader : public token_reader { const char *index; const char *separators; public: argument_parsing_token_reader(const char *s) { index = s; separators = "="; } int expects_exactly_one_option(void) { return 1; } virtual const char *get() { int length = strcspn(index, separators); if (length == 0) return NULL; const char *result = strndup(index, length); index += length; if (strspn(index, separators) >= 1) index++; separators = ","; return result; } virtual const char *peek() { int length = strcspn(index, separators); if (length == 0) return NULL; const char *result = strndup(index, length); return result; } virtual token_reader *divert(const char *open_token, const char *close_token) { assert(0); return NULL; } }; class cstring_token_reader : public token_reader { const char *separators; const char *string; int ephemeral; cstring_token_reader(const char *s, int ephemeral) { assert(ephemeral == 1); separators = "\n \t"; string = s; this->ephemeral = 1; } public: cstring_token_reader(const char *s) { separators = "\n \t"; string = s; ephemeral = 0; } const char *get() { string += strspn(string, separators); size_t length_to_next = strcspn(string, separators); if (length_to_next == 0) return NULL; const char *result = strndup(string, length_to_next); string += length_to_next; return result; } const char *peek() { string += strspn(string, separators); size_t length_to_next = strcspn(string, separators); if (length_to_next == 0) return NULL; return strndup(string, length_to_next); } cstring_token_reader *divert(const char *open_token, const char *close_token) { /* * This function might be broken. */ assert(0); int search = 0; int next = strcspn(string, separators); int depth = 0; while (*(string + search) != '\0' && (depth || strcmp(close_token, (string + search)))) { if (!strcmp(close_token, (string + search))) depth--; if (!strcmp(open_token, (string + search))) depth++; search = next; next = strcspn((string + next), separators); } if (*(string + search) == '\0') { fprintf(stderr, "Parse error: End of scope not found."); exit(1); } cstring_token_reader *result = new cstring_token_reader(strndup(string, search), 1); string += search; /* * Eat the closing token. */ get(); return result; } ~cstring_token_reader() { if (ephemeral) free((void *) string); } }; class cli_token_reader : public token_reader { int arg_index; int argc; const char **argv; public: cli_token_reader(int c, const char *v[]) { argc = c; argv = v; arg_index = 0; } const char *get() { if (arg_index < argc) return argv[arg_index++]; else return NULL; } const char *peek() { if (arg_index < argc) return argv[arg_index]; else return NULL; } cli_token_reader *divert(const char *open_token, const char *close_token) { int search = 0; int depth = 0; while (arg_index + search < argc && (depth || strcmp(argv[arg_index + search], close_token))) { if (!strcmp(close_token, argv[arg_index + search])) depth--; if (!strcmp(open_token, argv[arg_index + search])) depth++; search++; } if (arg_index + search == argc) { fprintf(stderr, "Parse error: end of scope not found.\n"); exit(1); } cli_token_reader *result = new cli_token_reader(search, argv + arg_index); arg_index += search; /* * Eat the closing token. */ get(); return result; } }; struct simple_option { const char *name; const char *map_name; const char *map_value; int arg_count; int multi; }; static const char *supported_nonglobal_option_table[]; static const char *focus_prefixes[]; static simple_option simple_option_table[]; static int option_name_match(const char *unadorned, const char *token, int require_ornamentation = 1) { int strip_max = 2; if (!strcmp(unadorned, token) && !require_ornamentation) return 1; while (token[0] == '-' && strip_max) { token++; strip_max--; if (!strcmp(unadorned, token)) return 1; } return 0; } static int is_scope_operator(const char *string) { if (!strcmp("{", string) || !strcmp("}", string) || !strcmp("[", string) || !strcmp("]", string) || !strcmp("<", string) || !strcmp(">", string)) return 1; return 0; } static const char *option_name_gen(const char *unadorned, const char *map_name, int arg_num, int multi) { static unsigned int multi_counter = 0; if (map_name) { unadorned = map_name; } int length = (strlen(unadorned) + sizeof(unsigned int) * 3 + sizeof(int) * 3 + 2) + 1; char *result = (char *) malloc(sizeof(char) * length); assert (result); if (!multi) { snprintf(result, length, "%u 0 %s", arg_num, unadorned); } else { /* * XXX: This assumes that generating calls for * options other than 0 exist in the same * multiplicity group as the most recently * generated 0-option multiplicity. */ if (arg_num == 0) multi_counter++; snprintf(result, length, "%u %u %s", arg_num, multi_counter, unadorned); } return result; } static environment *genv; static const char *get_next(token_reader *tr, const char *option_name) { const char *argument = tr->get(); if (argument == NULL) { fprintf(stderr, "\n\nError: not enough arguments for `%s'.\n\n", option_name); exit(1); } return argument; } static int table_contains(const char **haystack, const char *needle, int prefix_length = 0) { if (needle == NULL) return 0; while (*haystack != NULL) { if (prefix_length == 0 && !strcmp(*haystack, needle)) return 1; if (prefix_length > 0 && !strncmp(*haystack, needle, prefix_length)) return 1; haystack++; } return 0; } static int option_is_identical(environment *a, environment *b, const char *option_name) { if (!a->is_option(option_name) || !b->is_option(option_name)) return 0; int option_number = 0; while (a->is_arg(option_name, option_number) || b->is_arg(option_name, option_number)) { if (!a->is_arg(option_name, option_number) || !b->is_arg(option_name, option_number)) return 0; const char *a_str = a->get_string_arg(option_name, option_number); const char *b_str = b->get_string_arg(option_name, option_number); if (strcmp(a_str, b_str)) return 0; option_number++; } return 1; } static void remove_option(environment *a, const char *option_name) { assert(a->is_option(option_name)); int option_number = 0; while (a->is_arg(option_name, option_number)) { a->remove_arg(option_name, option_number); option_number++; } } static void remove_nonglobals(environment *a) { assert(a); std::stack removal_stack; for (std::map::iterator i = a->get_map().begin(); i != a->get_map().end(); i++) { if (!a->is_option(i->first)) continue; if (!table_contains(supported_nonglobal_option_table, a->get_option_name(i->first))) continue; removal_stack.push(i->first); } while (!removal_stack.empty()) { remove_option(a, removal_stack.top()); removal_stack.pop(); } } static void option_intersect(environment *a, environment *b) { assert(a); assert(b); std::stack removal_stack; for (std::map::iterator i = a->get_map().begin(); i != a->get_map().end(); i++) { if (!a->is_option(i->first)) continue; if (option_is_identical(a, b, i->first)) continue; removal_stack.push(i->first); } while (!removal_stack.empty()) { remove_option(a, removal_stack.top()); removal_stack.pop(); } } static void option_difference(environment *a, environment *b) { assert(a); assert(b); std::stack removal_stack; for (std::map::iterator i = a->get_map().begin(); i != a->get_map().end(); i++) { if (!a->is_option(i->first)) continue; if (!option_is_identical(a, b, i->first)) continue; removal_stack.push(i->first); } while (!removal_stack.empty()) { remove_option(a, removal_stack.top()); removal_stack.pop(); } } static void evaluate_stream(token_reader *tr, std::vector > *files) { const char *token; int end_of_options = 0; while ((token = tr->get())) { /* * Check for nesting */ if (!strcmp(token, "{") && !end_of_options) { environment::push_and_dup_output(); token_reader *tr_nest = tr->divert("{", "}"); evaluate_stream(tr_nest, files); delete tr_nest; environment::pop(); } else if (!strcmp(token, "[") && !end_of_options) { global_options = 0; environment::push(); token_reader *tr_nest = tr->divert("[", "]"); evaluate_stream(tr_nest, files); delete tr_nest; environment::pop(); } else if (!strcmp(token, "<") && !end_of_options) { environment *dup_list = environment::get_env(environment::top()->get("---dup")); assert (dup_list != NULL); dup_list = dup_list->clone(); environment::dup_second(); token_reader *tr_nest = tr->divert("<", ">"); evaluate_stream(tr_nest, files); delete tr_nest; environment::top()->set_ptr("---dup", dup_list); } /* * Check for non-whitespace argument separators */ else if (!end_of_options && token && token[0] == '-' && strchr(token, '=')) { environment::push_and_dup_output(); token_reader *tr_nest = new argument_parsing_token_reader(token); evaluate_stream(tr_nest, files); delete tr_nest; environment::pop(); } /* * Trap the end-of-option indicator. */ else if (!strcmp(token, "--")) { global_options = 0; end_of_options = 1; } /* * Check for options and filenames */ else { /* * Handle filenames. */ if (strncmp("-", token, strlen("-")) || end_of_options) { assert(files); global_options = 0; files->push_back(std::pair(strdup(token), environment::top()->clone())); if (tr->expects_exactly_one_option() && tr->get()) { fprintf(stderr, "\n\nError: Too many arguments for `%s'.\n\n", token); exit(1); } continue; } /* * Handle focus option. */ if (option_name_match("focus", token)) { environment *target; target = environment::top(); target->set_with_dup(option_name_gen("focus", NULL, 0, 0), "1"); const char *option = get_next(tr, "focus"); target->set_with_dup(option_name_gen("focus", NULL, 1, 0), option); if (!strcmp(option, "d")) { target->set_with_dup(option_name_gen("focus", NULL, 2, 0), get_next(tr, "focus")); } else if (!strcmp(option, "p")) { target->set_with_dup(option_name_gen("focus", NULL, 2, 0), get_next(tr, "focus")); target->set_with_dup(option_name_gen("focus", NULL, 3, 0), get_next(tr, "focus")); } else bad_arg("focus"); int arg = 0; while (table_contains(focus_prefixes, tr->peek(), 3)) { target->set_with_dup(option_name_gen("focus", NULL, 4 + arg, 0), get_next(tr, "focus")); arg++; } continue; } /* * Handle simple options. */ int found_option = 0; for (int i = 0; simple_option_table[i].name; i++) { if (!option_name_match(simple_option_table[i].name, token)) continue; /* * Handle the match case. */ found_option = 1; /* * Determine which environment should be modified */ environment *target; target = environment::top(); /* * Store information required for * handling the local case later. */ const char *map_value = "1"; if (simple_option_table[i].map_value) { map_value = simple_option_table[i].map_value; } else if (simple_option_table[i].map_name) { map_value = simple_option_table[i].name; } target->set_with_dup(option_name_gen(simple_option_table[i].name, simple_option_table[i].map_name, 0, simple_option_table[i].multi), map_value); for (int j = 0; j < simple_option_table[i].arg_count; j++) { const char *option = tr->get(); if (option == NULL) { fprintf(stderr, "\n\nError: not enough options for `%s'.\n\n", token); exit(1); } /* * Reject scope operators as options, * at least for now. */ if (is_scope_operator(option)) { fprintf(stderr, "\n\nError: illegal argument to `%s'.\n\n", token); exit(1); } target->set_with_dup(option_name_gen(simple_option_table[i].name, simple_option_table[i].map_name, j + 1, simple_option_table[i].multi), option); } } /* * Trap illegal options. */ if (!found_option) ui::get()->illegal_option(token); } if (tr->expects_exactly_one_option() && tr->get()) { fprintf(stderr, "\n\nError: Too many arguments for `%s'.\n\n", token); exit(1); } } } public: /* * Input handler. * * Does one of two things: * * (1) Output version information if called with '--version' * * (2) Read options and file arguments, and if the arguments are correct, * write output. If an error is detected, print the usage statement. * */ static void handle(int argc, const char *argv[], const char *package, const char *short_version, const char *version) { /* * Initialize help object */ help hi(package, argv[0], short_version); /* * Output version information if --version appears * on the command line. */ if (arg_count(argc, argv, "--version")) { /* * Output the version */ fprintf(stdout, "%s", version); return; } /* * Handle help options */ if (arg_prefix_count(argc, argv, "--h")) for (int i = 1; i < argc; i++) { int all = !strcmp(argv[i], "--hA"); int is_help_option = !strncmp(argv[i], "--h", strlen("--h")); int found_help = 0; if (!strcmp(argv[i], "--hu") || all) hi.usage(), found_help = 1; if (!strcmp(argv[i], "--hq") || all) hi.defaults(), found_help = 1; if (!strcmp(argv[i], "--hf") || all) hi.file(), found_help = 1; if (!strcmp(argv[i], "--he") || all) hi.exclusion(), found_help = 1; if (!strcmp(argv[i], "--ha") || all) hi.alignment(), found_help = 1; if (!strcmp(argv[i], "--hr") || all) hi.rendering(), found_help = 1; if (!strcmp(argv[i], "--hx") || all) hi.exposure(), found_help = 1; if (!strcmp(argv[i], "--ht") || all) hi.tdf(), found_help = 1; if (!strcmp(argv[i], "--hl") || all) hi.filtering(), found_help = 1; if (!strcmp(argv[i], "--hd") || all) hi.device(), found_help = 1; if (!strcmp(argv[i], "--hi") || all) hi.interface(), found_help = 1; if (!strcmp(argv[i], "--hv") || all) hi.visp(), found_help = 1; if (!strcmp(argv[i], "--hc") || all) hi.cp(), found_help = 1; if (!strcmp(argv[i], "--h3") || all) hi.d3(), found_help = 1; if (!strcmp(argv[i], "--hs") || all) hi.scope(), found_help = 1; if (!strcmp(argv[i], "--hp") || all) hi.process(), found_help = 1; if (!strcmp(argv[i], "--hz") || all) hi.undocumented(), found_help = 1; if (is_help_option && !found_help) hi.usage(); /* * Check for the end-of-options marker, a non-option argument, * or the end of arguments. In all of these cases, we exit. */ if (!strcmp(argv[i], "--") || strncmp(argv[i], "--", strlen("--")) || i == argc - 1) return; } /* * Undocumented projective transformation utility */ if (arg_count(argc, argv, "--ptcalc") > 0) { fprintf(stderr, "\n\n*** Warning: this feature is not documented ***\n\n"); printf("Enter: w h tlx tly blx bly brx bry trx try x y\n\n"); double w, h, tlx, tly, blx, bly, brx, bry, trx, tr_y, x, y; printf("> "); if (scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf", &w, &h, &tlx, &tly, &blx, &bly, &brx, &bry, &trx, &tr_y, &x, &y) != 12) { fprintf(stderr, "Error reading input.\n"); exit(1); } d2::image *i = d2::new_image_ale_real((int)h, (int)w, 3); d2::transformation t = d2::transformation::gpt_identity(i, 1); d2::point q[4] = { d2::point(tly, tlx), d2::point(bly, blx), d2::point(bry, brx), d2::point(tr_y, trx) }; t.gpt_set(q); d2::point a(y, x), b; b = t.transform_scaled(a); printf("TRANSFORM t(a): (%f, %f)\n", (double) b[1], (double) b[0]); b = t.scaled_inverse_transform(a); printf("INVERSE t^-1(a): (%f, %f)\n", (double) b[1], (double) b[0]); exit(0); } /* * Thread initialization. */ thread::init(); /* * Flags and variables */ double scale_factor = 1; double vise_scale_factor = 1; #if 0 double usm_multiplier = 0.0; #endif int extend = 0; struct d2::tload_t *tload = NULL; struct d2::tsave_t *tsave = NULL; struct d3::tload_t *d3_tload = NULL; struct d3::tsave_t *d3_tsave = NULL; int ip_iterations = 0; int ip_use_median = 0; double ipwl = 0; enum { psf_linear, psf_nonlinear, psf_N }; const char *psf[psf_N] = {NULL, NULL}; const char *device = NULL; int psf_match = 0; double psf_match_args[6]; int inc = 0; int exposure_register = 1; const char *wm_filename = NULL; int wm_offsetx = 0, wm_offsety = 0; double cx_parameter = 1; double *d3px_parameters = NULL; int d3px_count = 0; d2::exclusion *ex_parameters = NULL; int ex_count = 0; int ex_show = 0; d2::render *achain; const char *achain_type = "triangle:2"; const char *afilter_type = "internal"; d2::render **ochain = NULL; const char **ochain_names = NULL; const char **ochain_types = NULL; const char *d3chain_type = NULL; int oc_count = 0; const char **visp = NULL; int vise_count = 0; const char **d3_output = NULL; const char **d3_depth = NULL; unsigned int d3_count = 0; double user_view_angle = 0; int user_bayer = IMAGE_BAYER_DEFAULT; d2::pixel exp_mult = d2::pixel(1, 1, 1); std::map d3_output_pt; std::map d3_depth_pt; /* * dchain is ochain[0]. */ ochain = (d2::render **) local_realloc(ochain, (oc_count + 1) * sizeof(d2::render *)); ochain_names = (const char **) local_realloc((void *)ochain_names, (oc_count + 1) * sizeof(const char *)); ochain_types = (const char **) local_realloc((void *)ochain_types, (oc_count + 1) * sizeof(const char *)); ochain_types[0] = "sinc*lanc:8"; oc_count = 1; /* * Handle default settings */ if (arg_prefix_count(argc, argv, "--q") > 0) ui::get()->error("Default settings --q* are no longer recognized."); #define FIXED16 4 #if ALE_COLORS == FIXED16 const char *defaults = "--dchain auto:triangle:2,fine:box:1,triangle:2 " "--achain triangle:2 " "--ips 0 " "--3d-chain fine:triangle:2,fine:gauss:0.75,triangle:2 "; #else const char *defaults = "--dchain auto:triangle:2,fine:box:1,triangle:2 " "--achain triangle:2 " "--ips 1 " "--3d-chain fine:triangle:2,fine:gauss:0.75,triangle:2 "; #endif #undef FIXED16 token_reader *default_reader = new cstring_token_reader(defaults); evaluate_stream(default_reader, NULL); /* * Set basic program information in the environment. */ environment::top()->set_with_dup("---package", package); environment::top()->set_with_dup("---short-version", short_version); environment::top()->set_with_dup("---version", version); environment::top()->set_with_dup("---invocation", argv[0]); /* * Initialize the top-level token-reader and generate * an environment variable for it. */ token_reader *tr = new cli_token_reader(argc - 1, argv + 1); environment::top()->set_ptr("---token-reader", tr); /* * Evaluate the command-line arguments to generate environment * structures. */ std::vector > files; evaluate_stream(tr, &files); /* * If there are fewer than two files, then output usage information. */ if (files.size() < 2) { hi.usage(); exit(1); } /* * Extract the global environment and check non-globals * against a list of supported non-global options. */ genv = files[0].second->clone(); remove_nonglobals(genv); for (unsigned int i = 0; i < files.size(); i++) { option_intersect(genv, files[i].second); } for (unsigned int i = 0; i < files.size(); i++) { option_difference(files[i].second, genv); for (std::map::iterator j = files[i].second->get_map().begin(); j != files[i].second->get_map().end(); j++) { environment *env = files[i].second; if (!env->is_option(j->first)) continue; const char *option_name = env->get_option_name(j->first); if (!table_contains(supported_nonglobal_option_table, option_name)) { fprintf(stderr, "\n\nError: option `%s' must be applied globally.", option_name); fprintf(stderr, "\n\nHint: Move option `%s' prior to file and scope operators.\n\n", option_name); exit(1); } } } /* * Iterate through the global environment, * looking for options. */ for (std::map::iterator i = genv->get_map().begin(); i != genv->get_map().end(); i++) { environment *env = genv; if (!env->is_option(i->first)) continue; const char *option_name = env->get_option_name(i->first); if (!strcmp(option_name, "default")) { /* * Do nothing. Defaults have already been set. */ } else if (!strcmp(option_name, "bpc")) { if (!strcmp(env->get_string_arg(i->first, 0), "8bpc")) d2::image_rw::depth8(); else if (!strcmp(env->get_string_arg(i->first, 0), "16bpc")) d2::image_rw::depth16(); else assert(0); } else if (!strcmp(option_name, "format")) { if (!strcmp(env->get_string_arg(i->first, 0), "plain")) d2::image_rw::ppm_plain(); else if (!strcmp(env->get_string_arg(i->first, 0), "raw")) d2::image_rw::ppm_raw(); else if (!strcmp(env->get_string_arg(i->first, 0), "auto")) d2::image_rw::ppm_auto(); else assert(0); } else if (!strcmp(option_name, "align")) { if (!strcmp(env->get_string_arg(i->first, 0), "align-all")) d2::align::all(); else if (!strcmp(env->get_string_arg(i->first, 0), "align-green")) d2::align::green(); else if (!strcmp(env->get_string_arg(i->first, 0), "align-sum")) d2::align::sum(); else assert(0); } else if (!strcmp(option_name, "transformation")) { if (!strcmp(env->get_string_arg(i->first, 0), "translation")) d2::align::class_translation(); else if (!strcmp(env->get_string_arg(i->first, 0), "euclidean")) d2::align::class_euclidean(); else if (!strcmp(env->get_string_arg(i->first, 0), "projective")) d2::align::class_projective(); else assert(0); } else if (!strcmp(option_name, "transformation-default")) { if (!strcmp(env->get_string_arg(i->first, 0), "identity")) d2::align::initial_default_identity(); else if (!strcmp(env->get_string_arg(i->first, 0), "follow")) d2::align::initial_default_follow(); else assert(0); } else if (!strcmp(option_name, "perturb")) { if (!strcmp(env->get_string_arg(i->first, 0), "perturb-output")) d2::align::perturb_output(); else if (!strcmp(env->get_string_arg(i->first, 0), "perturb-source")) d2::align::perturb_source(); else assert(0); } else if (!strcmp(option_name, "fail")) { if (!strcmp(env->get_string_arg(i->first, 0), "fail-optimal")) d2::align::fail_optimal(); else if (!strcmp(env->get_string_arg(i->first, 0), "fail-default")) d2::align::fail_default(); else assert(0); } else if (!strcmp(option_name, "profile")) { ui::set_profile(); } else if (!strcmp(option_name, "extend")) { if (env->get_int_arg(i->first, 0)) extend = 1; else extend = 0; } else if (!strcmp(option_name, "oc")) { if (env->get_int_arg(i->first, 0)) d3::scene::oc(); else d3::scene::no_oc(); } else if (!strcmp(option_name, "focus")) { double one = +1; double zero = +0; double inf = one / zero; assert (isinf(inf) && inf > 0); /* * Focus type */ unsigned int type = 0; double distance = 0; double px = 0, py = 0; if (!strcmp(env->get_string_arg(i->first, 1), "d")) { type = 0; distance = env->get_double_arg(i->first, 2); } else if (!strcmp(env->get_string_arg(i->first, 1), "p")) { type = 1; px = env->get_double_arg(i->first, 2); py = env->get_double_arg(i->first, 3); } else { bad_arg(option_name); } /* * Options */ unsigned int ci = 0; double fr = 0; double ht = 0; double vt = 0; double sd = 0; double ed = inf; double sx = -inf; double ex = inf; double sy = -inf; double ey = inf; double ap = 3; unsigned int sc = 3; unsigned int fs = 0; unsigned int sr = 0; for (int arg_num = 4; env->is_arg(i->first, arg_num); arg_num++) { const char *option = env->get_string_arg(i->first, arg_num); if (!strncmp(option, "ci=", 3)) { if(sscanf(option + 3, "%u", &ci) != 1) bad_arg("--focus"); } else if (!strncmp(option, "fr=", 3)) { if(sscanf(option + 3, "%lf", &fr) != 1) bad_arg("--focus"); } else if (!strncmp(option, "ht=", 3)) { if(sscanf(option + 3, "%lf", &ht) != 1) bad_arg("--focus"); } else if (!strncmp(option, "vt=", 3)) { if(sscanf(option + 3, "%lf", &vt) != 1) bad_arg("--focus"); } else if (!strncmp(option, "sy=", 3)) { if(sscanf(option + 3, "%lf", &sy) != 1) bad_arg("--focus"); } else if (!strncmp(option, "ey=", 3)) { if(sscanf(option + 3, "%lf", &ey) != 1) bad_arg("--focus"); } else if (!strncmp(option, "sx=", 3)) { if(sscanf(option + 3, "%lf", &sx) != 1) bad_arg("--focus"); } else if (!strncmp(option, "ex=", 3)) { if(sscanf(option + 3, "%lf", &ex) != 1) bad_arg("--focus"); } else if (!strncmp(option, "sd=", 3)) { if(sscanf(option + 3, "%lf", &sd) != 1) bad_arg("--focus"); } else if (!strncmp(option, "ed=", 3)) { if(sscanf(option + 3, "%lf", &ed) != 1) bad_arg("--focus"); } else if (!strncmp(option, "ap=", 3)) { if(sscanf(option + 3, "%lf", &ap) != 1) bad_arg("--focus"); } else if (!strncmp(option, "sc=", 3)) { if(sscanf(option + 3, "%u", &sc) != 1) bad_arg("--focus"); } else if (!strncmp(option, "sr=", 3)) { if (!strcmp(option, "sr=aperture")) { sr = 0; } else if (!strcmp(option, "sr=pixel")) { sr = 1; } else bad_arg("--focus"); } else if (!strncmp(option, "fs=", 3)) { if (!strcmp(option, "fs=mean")) { fs = 0; } else if (!strcmp(option, "fs=median")) { fs = 1; } else bad_arg("--focus"); } else bad_arg("--focus"); } d3::focus::add_region(type, distance, px, py, ci, fr, ht, vt, sd, ed, sx, ex, sy, ey, ap, sc, fs, sr); } else if (!strcmp(option_name, "3ddp") || !strcmp(option_name, "3dvp")) { d2::align::keep(); /* * Unsupported configurations */ if (ip_iterations) unsupported::fornow("3D modeling with Irani-Peleg rendering"); #if 0 if (usm_multiplier) unsupported::fornow("3D modeling with unsharp mask"); #endif /* * Initialize if necessary * * Note: because their existence is checked as an * indicator of the presence of 3D arguments, we * initialize these structures here. */ if (d3_output == NULL) { d3_count = argc; d3_output = (const char **) calloc(d3_count, sizeof(char *)); d3_depth = (const char **) calloc(d3_count, sizeof(char *)); } unsigned int width, height; double view_angle; double x, y, z; double P, Y, R; width = env->get_unsigned_arg(i->first, 1); height = env->get_unsigned_arg(i->first, 2); view_angle = env->get_double_arg(i->first, 3); x = env->get_double_arg(i->first, 4); y = env->get_double_arg(i->first, 5); z = env->get_double_arg(i->first, 6); P = env->get_double_arg(i->first, 7); Y = env->get_double_arg(i->first, 8); R = env->get_double_arg(i->first, 9); view_angle *= M_PI / 180; P *= M_PI / 180; Y *= M_PI / 180; R *= M_PI / 180; d2::transformation t = d2::transformation::eu_identity(); t.set_domain(height, width); d3::pt _pt(t, d3::et(y, x, z, Y, P, R), view_angle); if (!strcmp(option_name, "3dvp")) { d3_output_pt[env->get_string_arg(i->first, 10)] = _pt; } else if (!strcmp(option_name, "3ddp")) { d3_depth_pt[env->get_string_arg(i->first, 10)] = _pt; } else { assert(0); } } else if (!strcmp(option_name, "3dv")) { d2::align::keep(); unsigned int frame_no; /* * Unsupported configurations */ if (ip_iterations) unsupported::fornow("3D modeling with Irani-Peleg rendering"); #if 0 if (usm_multiplier) unsupported::fornow("3D modeling with unsharp mask"); #endif /* * Initialize if necessary */ if (d3_output == NULL) { d3_count = argc; d3_output = (const char **) calloc(d3_count, sizeof(char *)); d3_depth = (const char **) calloc(d3_count, sizeof(char *)); } frame_no = env->get_int_arg(i->first, 1); if (frame_no >= d3_count) ui::get()->error("--3dv argument 0 is too large"); if (d3_output[frame_no] != NULL) { unsupported::fornow ("Writing a single 3D view to more than one output file"); } d3_output[frame_no] = env->get_string_arg(i->first, 2); } else if (!strcmp(option_name, "3dd")) { d2::align::keep(); unsigned int frame_no; /* * Unsupported configurations */ if (ip_iterations) unsupported::fornow("3D modeling with Irani-Peleg rendering"); #if 0 if (usm_multiplier) unsupported::fornow("3D modeling with unsharp mask"); #endif /* * Initialize if necessary */ if (d3_output == NULL) { d3_count = argc; d3_output = (const char **) calloc(d3_count, sizeof(char *)); d3_depth = (const char **) calloc(d3_count, sizeof(char *)); } frame_no = env->get_int_arg(i->first, 1); if (frame_no >= d3_count) ui::get()->error("--3dd argument 0 is too large"); if (d3_depth[frame_no] != NULL) { unsupported::fornow ("Writing a single frame's depth info to more than one output file"); } d3_depth[frame_no] = env->get_string_arg(i->first, 2); } else if (!strcmp(option_name, "view-angle")) { user_view_angle = env->get_double_arg(i->first, 1) * M_PI / 180; } else if (!strcmp(option_name, "cpf-load")) { d3::cpf::init_loadfile(env->get_string_arg(i->first, 1)); } else if (!strcmp(option_name, "ui")) { if (!strcmp(env->get_string_arg(i->first, 1), "stream")) ui::set_stream(); else if (!strcmp(env->get_string_arg(i->first, 1), "tty")) ui::set_tty(); else if (!strcmp(env->get_string_arg(i->first, 1), "log")) ui::set_log(); else if (!strcmp(env->get_string_arg(i->first, 1), "quiet")) ui::set_quiet(); else { fprintf(stderr, "Error: Unknown user interface type '%s'\n", env->get_string_arg(i->first, 1)); exit(1); } } else if (!strcmp(option_name, "3d-fmr")) { d3::scene::fmr(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "3d-dmr")) { d3::scene::dmr(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "et")) { d3::scene::et(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "st")) { d3::cpf::st(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "di-lower")) { d3::scene::di_lower(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "rc")) { d3::scene::rc(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "do-try")) { d3::scene::do_try(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "di-upper")) { d3::scene::di_upper(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "fc")) { d3::scene::fc(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "ecm")) { unsupported::discontinued("--ecm "); } else if (!strcmp(option_name, "acm")) { unsupported::discontinued("--acm "); } else if (!strcmp(option_name, "def-nn")) { d2::image_rw::def_nn(env->get_double_arg(i->first, 1)); if (env->get_double_arg(i->first, 1) > 2) { fprintf(stderr, "\n\n*** Warning: --def-nn implementation is currently " "inefficient for large radii. ***\n\n"); } } else if (!strcmp(option_name, "fx")) { d3::scene::fx(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "tcem")) { d3::scene::tcem(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "oui")) { d3::scene::oui(env->get_unsigned_arg(i->first, 1)); } else if (!strcmp(option_name, "pa")) { d3::scene::pa(env->get_unsigned_arg(i->first, 1)); } else if (!strcmp(option_name, "pc")) { d3::scene::pc(env->get_string_arg(i->first, 1)); } else if (!strcmp(option_name, "cw")) { d2::align::certainty_weighted(env->get_unsigned_arg(i->first, 0)); } else if (!strcmp(option_name, "wm")) { if (wm_filename != NULL) ui::get()->error("only one weight map can be specified"); wm_filename = env->get_string_arg(i->first, 1); wm_offsetx = env->get_int_arg(i->first, 2); wm_offsety = env->get_int_arg(i->first, 3); } else if (!strcmp(option_name, "fl")) { #ifdef USE_FFTW d2::align::set_frequency_cut(env->get_double_arg(i->first, 1), env->get_double_arg(i->first, 2), env->get_double_arg(i->first, 3)); #else ui::get()->error_hint("--fl is not supported", "rebuild ALE with FFTW support"); #endif } else if (!strcmp(option_name, "wmx")) { #ifdef USE_UNIX d2::align::set_wmx(env->get_string_arg(i->first, 1), env->get_string_arg(i->first, 2), env->get_string_arg(i->first, 3)); #else ui::get()->error_hint("--wmx is not supported", "rebuild ALE with support for --wmx"); #endif } else if (!strcmp(option_name, "flshow")) { d2::align::set_fl_show(env->get_string_arg(i->first, 1)); } else if (!strcmp(option_name, "3dpx")) { d3px_parameters = (double *) local_realloc(d3px_parameters, (d3px_count + 1) * 6 * sizeof(double)); for (int param = 0; param < 6; param++) d3px_parameters[6 * d3px_count + param] = env->get_double_arg(i->first, param + 1); /* * Swap x and y, since their internal meanings differ from their external meanings. */ for (int param = 0; param < 2; param++) { double temp = d3px_parameters[6 * d3px_count + 2 + param]; d3px_parameters[6 * d3px_count + 2 + param] = d3px_parameters[6 * d3px_count + 0 + param]; d3px_parameters[6 * d3px_count + 0 + param] = temp; } /* * Increment counters */ d3px_count++; } else if (!strcmp(option_name, "ex") || !strcmp(option_name, "fex")) { ex_parameters = (d2::exclusion *) local_realloc(ex_parameters, (ex_count + 1) * sizeof(d2::exclusion)); ex_parameters[ex_count].type = (!strcmp(option_name, "ex")) ? d2::exclusion::RENDER : d2::exclusion::FRAME; /* * Get parameters, swapping x and y coordinates */ ex_parameters[ex_count].x[0] = env->get_int_arg(i->first, 1 + 2); ex_parameters[ex_count].x[1] = env->get_int_arg(i->first, 1 + 3); ex_parameters[ex_count].x[2] = env->get_int_arg(i->first, 1 + 0); ex_parameters[ex_count].x[3] = env->get_int_arg(i->first, 1 + 1); ex_parameters[ex_count].x[4] = env->get_int_arg(i->first, 1 + 4); ex_parameters[ex_count].x[5] = env->get_int_arg(i->first, 1 + 5); /* * Increment counters */ ex_count++; } else if (!strcmp(option_name, "crop") || !strcmp(option_name, "fcrop")) { ex_parameters = (d2::exclusion *) local_realloc(ex_parameters, (ex_count + 4) * sizeof(d2::exclusion)); for (int r = 0; r < 4; r++) ex_parameters[ex_count + r].type = (!strcmp(option_name, "crop")) ? d2::exclusion::RENDER : d2::exclusion::FRAME; int crop_args[6]; for (int param = 0; param < 6; param++) crop_args[param] = env->get_int_arg(i->first, param + 1); /* * Construct exclusion regions from the crop area, * swapping x and y, since their internal meanings * differ from their external meanings. */ /* * Exclusion region 1: low x */ ex_parameters[ex_count + 0].x[0] = INT_MIN; ex_parameters[ex_count + 0].x[1] = crop_args[2] - 1; ex_parameters[ex_count + 0].x[2] = INT_MIN; ex_parameters[ex_count + 0].x[3] = INT_MAX; ex_parameters[ex_count + 0].x[4] = crop_args[4]; ex_parameters[ex_count + 0].x[5] = crop_args[5]; /* * Exclusion region 2: low y */ ex_parameters[ex_count + 1].x[0] = INT_MIN; ex_parameters[ex_count + 1].x[1] = INT_MAX; ex_parameters[ex_count + 1].x[2] = INT_MIN; ex_parameters[ex_count + 1].x[3] = crop_args[0] - 1; ex_parameters[ex_count + 1].x[4] = crop_args[4]; ex_parameters[ex_count + 1].x[5] = crop_args[5]; /* * Exclusion region 3: high y */ ex_parameters[ex_count + 2].x[0] = INT_MIN; ex_parameters[ex_count + 2].x[1] = INT_MAX; ex_parameters[ex_count + 2].x[2] = crop_args[1] + 1; ex_parameters[ex_count + 2].x[3] = INT_MAX; ex_parameters[ex_count + 2].x[4] = crop_args[4]; ex_parameters[ex_count + 2].x[5] = crop_args[5]; /* * Exclusion region 4: high x */ ex_parameters[ex_count + 3].x[0] = crop_args[3] + 1; ex_parameters[ex_count + 3].x[1] = INT_MAX; ex_parameters[ex_count + 3].x[2] = INT_MIN; ex_parameters[ex_count + 3].x[3] = INT_MAX; ex_parameters[ex_count + 3].x[4] = crop_args[4]; ex_parameters[ex_count + 3].x[5] = crop_args[5]; /* * Increment counters */ ex_count += 4; } else if (!strcmp(option_name, "exshow")) { ex_show = 1; } else if (!strcmp(option_name, "wt")) { d2::render::set_wt(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "3d-chain")) { d3chain_type = env->get_string_arg(i->first, 1); } else if (!strcmp(option_name, "dchain")) { ochain_types[0] = env->get_string_arg(i->first, 1); } else if (!strcmp(option_name, "achain")) { achain_type = env->get_string_arg(i->first, 1); } else if (!strcmp(option_name, "afilter")) { afilter_type = env->get_string_arg(i->first, 1); } else if (!strcmp(option_name, "ochain")) { ochain = (d2::render **) local_realloc(ochain, (oc_count + 1) * sizeof(d2::render *)); ochain_names = (const char **) local_realloc((void *)ochain_names, (oc_count + 1) * sizeof(const char *)); ochain_types = (const char **) local_realloc((void *)ochain_types, (oc_count + 1) * sizeof(const char *)); ochain_types[oc_count] = env->get_string_arg(i->first, 1); ochain_names[oc_count] = env->get_string_arg(i->first, 2); oc_count++; } else if (!strcmp(option_name, "visp")) { visp = (const char **) local_realloc((void *)visp, 4 * (vise_count + 1) * sizeof(const char *)); for (int param = 0; param < 4; param++) visp[vise_count * 4 + param] = env->get_string_arg(i->first, param + 1); vise_count++; } else if (!strcmp(option_name, "cx")) { cx_parameter = env->get_int_arg(i->first, 0) ? env->get_double_arg(i->first, 1) : 0; } else if (!strcmp(option_name, "ip")) { unsupported::discontinued("--ip ", "--lpsf box= --ips "); } else if (!strcmp(option_name, "cache")) { double cache = env->get_double_arg(i->first, 1); d2::image_rw::set_cache(cache); } else if (!strcmp(option_name, "resident")) { double resident = env->get_double_arg(i->first, 1); d2::image::set_resident(resident); } else if (!strcmp(option_name, "bayer")) { /* * External order is clockwise from top-left. Internal * order is counter-clockwise from top-left. */ const char *option = env->get_string_arg(i->first, 1); if (!strcmp(option, "rgbg")) { user_bayer = IMAGE_BAYER_RGBG; } else if (!strcmp(option, "bgrg")) { user_bayer = IMAGE_BAYER_BGRG; } else if (!strcmp(option, "gbgr")) { user_bayer = IMAGE_BAYER_GRGB; } else if (!strcmp(option, "grgb")) { user_bayer = IMAGE_BAYER_GBGR; } else if (!strcmp(option, "none")) { user_bayer = IMAGE_BAYER_NONE; } else { bad_arg("--bayer"); } } else if (!strcmp(option_name, "lpsf")) { psf[psf_linear] = env->get_string_arg(i->first, 1); } else if (!strcmp(option_name, "nlpsf")) { psf[psf_nonlinear] = env->get_string_arg(i->first, 1); } else if (!strcmp(option_name, "psf-match")) { psf_match = 1; for (int index = 0; index < 6; index++) { psf_match_args[index] = env->get_double_arg(i->first, index + 1); } } else if (!strcmp(option_name, "device")) { device = env->get_string_arg(i->first, 1); #if 0 } else if (!strcmp(option_name, "usm")) { if (d3_output != NULL) unsupported::fornow("3D modeling with unsharp mask"); usm_multiplier = env->get_double_arg(i->first, 1); #endif } else if (!strcmp(option_name, "ipr")) { ip_iterations = env->get_int_arg(i->first, 1); ui::get()->warn("--ipr is deprecated. Use --ips instead"); } else if (!strcmp(option_name, "cpp-err")) { if (!strcmp(env->get_string_arg(i->first, 0), "median")) d3::cpf::err_median(); else if (!strcmp(env->get_string_arg(i->first, 0), "mean")) d3::cpf::err_mean(); } else if (!strcmp(option_name, "vp-adjust")) { if (env->get_int_arg(i->first, 0)) d3::align::vp_adjust(); else d3::align::vp_noadjust(); } else if (!strcmp(option_name, "vo-adjust")) { if (env->get_int_arg(i->first, 0)) d3::align::vo_adjust(); else d3::align::vo_noadjust(); } else if (!strcmp(option_name, "ip-statistic")) { if (!strcmp(env->get_string_arg(i->first, 0), "mean")) ip_use_median = 0; else if (!strcmp(env->get_string_arg(i->first, 0), "median")) ip_use_median = 1; } else if (!strcmp(option_name, "ips")) { ip_iterations = env->get_int_arg(i->first, 1); } else if (!strcmp(option_name, "ip-wl")) { int limited = env->get_int_arg(i->first, 0); if (limited) { ipwl = env->get_double_arg(i->first, 1); } else { ipwl = 0; } } else if (!strcmp(option_name, "ipc")) { unsupported::discontinued("--ipc ", "--ips --lpsf ", "--ips --device "); } else if (!strcmp(option_name, "exp-extend")) { if (env->get_int_arg(i->first, 0)) d2::image_rw::exp_scale(); else d2::image_rw::exp_noscale(); } else if (!strcmp(option_name, "exp-register")) { if (env->get_int_arg(i->first, 0) == 1) { exposure_register = 1; d2::align::exp_register(); } else if (env->get_int_arg(i->first, 0) == 0) { exposure_register = 0; d2::align::exp_noregister(); } else if (env->get_int_arg(i->first, 0) == 2) { exposure_register = 2; d2::align::exp_meta_only(); } } else if (!strcmp(option_name, "drizzle-only")) { unsupported::discontinued("--drizzle-only", "--dchain box:1"); } else if (!strcmp(option_name, "subspace-traverse")) { unsupported::undocumented("--subspace-traverse"); d3::scene::set_subspace_traverse(); } else if (!strcmp(option_name, "3d-filter")) { if (env->get_int_arg(i->first, 0)) d3::scene::filter(); else d3::scene::nofilter(); } else if (!strcmp(option_name, "occ-norm")) { if (env->get_int_arg(i->first, 0)) d3::scene::nw(); else d3::scene::no_nw(); } else if (!strcmp(option_name, "inc")) { inc = env->get_int_arg(i->first, 0); } else if (!strcmp(option_name, "exp-mult")) { double exp_c, exp_r, exp_b; exp_c = env->get_double_arg(i->first, 1); exp_r = env->get_double_arg(i->first, 2); exp_b = env->get_double_arg(i->first, 3); exp_mult = d2::pixel(1/(exp_r * exp_c), 1/exp_c, 1/(exp_b * exp_c)); } else if (!strcmp(option_name, "visp-scale")) { vise_scale_factor = env->get_double_arg(i->first, 1); if (vise_scale_factor <= 0.0) ui::get()->error("VISP scale must be greater than zero"); if (!finite(vise_scale_factor)) ui::get()->error("VISP scale must be finite"); } else if (!strcmp(option_name, "scale")) { scale_factor = env->get_double_arg(i->first, 1); if (scale_factor <= 0) ui::get()->error("Scale factor must be greater than zero"); if (!finite(scale_factor)) ui::get()->error("Scale factor must be finite"); } else if (!strcmp(option_name, "metric")) { d2::align::set_metric_exponent(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "threshold")) { d2::align::set_match_threshold(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "drizzle-diam")) { unsupported::discontinued("--drizzle-diam=", "--dchain box:1"); } else if (!strcmp(option_name, "perturb-lower")) { const char *option = env->get_string_arg(i->first, 1); double perturb_lower; int characters; sscanf(option, "%lf%n", &perturb_lower, &characters); if (perturb_lower <= 0) ui::get()->error("--perturb-lower= value is non-positive"); if (*(option + characters) == '%') d2::align::set_perturb_lower(perturb_lower, 1); else d2::align::set_perturb_lower(perturb_lower, 0); } else if (!strcmp(option_name, "stepsize")) { ui::get()->warn("--stepsize is deprecated. Use --perturb-lower instead"); d2::align::set_perturb_lower(env->get_double_arg(i->first, 1), 0); } else if (!strcmp(option_name, "va-upper")) { const char *option = env->get_string_arg(i->first, 1); double va_upper; int characters; sscanf(option, "%lf%n", &va_upper, &characters); if (*(option + characters) == '%') ui::get()->error("--va-upper= does not accept '%' arguments\n"); else d3::cpf::set_va_upper(va_upper); } else if (!strcmp(option_name, "cpp-upper")) { const char *option = env->get_string_arg(i->first, 1); double perturb_upper; int characters; sscanf(option, "%lf%n", &perturb_upper, &characters); if (*(option + characters) == '%') ui::get()->error("--cpp-upper= does not currently accept '%' arguments\n"); else d3::cpf::set_cpp_upper(perturb_upper); } else if (!strcmp(option_name, "cpp-lower")) { const char *option = env->get_string_arg(i->first, 1); double perturb_lower; int characters; sscanf(option, "%lf%n", &perturb_lower, &characters); if (*(option + characters) == '%') ui::get()->error("--cpp-lower= does not currently accept '%' arguments\n"); else d3::cpf::set_cpp_lower(perturb_lower); } else if (!strcmp(option_name, "hf-enhance")) { unsupported::discontinued("--hf-enhance="); } else if (!strcmp(option_name, "multi")) { d2::trans_multi::set_multi(env->get_string_arg(i->first, 1)); } else if (!strcmp(option_name, "gs")) { d2::align::gs(env->get_string_arg(i->first, 1)); } else if (!strcmp(option_name, "rot-upper")) { d2::align::set_rot_max((int) floor(env->get_double_arg(i->first, 1))); } else if (!strcmp(option_name, "bda-mult")) { d2::align::set_bda_mult(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "bda-rate")) { d2::align::set_bda_rate(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "lod-preferred")) { d2::align::set_lod_preferred((int) floor(env->get_double_arg(i->first, 1))); } else if (!strcmp(option_name, "min-dimension")) { d2::align::set_min_dimension((int) ceil(env->get_double_arg(i->first, 1))); } else if (!strcmp(option_name, "cpf-load")) { d3::cpf::init_loadfile(env->get_string_arg(i->first, 1)); #if 0 } else if (!strcmp(option_name, "model-load")) { d3::scene::load_model(env->get_string_arg(i->first, 1)); } else if (!strcmp(option_name, "model-save")) { d3::scene::save_model(env->get_string_arg(i->first, 1)); #endif } else if (!strcmp(option_name, "trans-load")) { d2::tload_delete(tload); tload = d2::tload_new(env->get_string_arg(i->first, 1)); d2::align::set_tload(tload); } else if (!strcmp(option_name, "trans-save")) { tsave_delete(tsave); tsave = d2::tsave_new(env->get_string_arg(i->first, 1)); d2::align::set_tsave(tsave); } else if (!strcmp(option_name, "3d-trans-load")) { d3::tload_delete(d3_tload); d3_tload = d3::tload_new(env->get_string_arg(i->first, 1)); d3::align::set_tload(d3_tload); } else if (!strcmp(option_name, "3d-trans-save")) { d3::tsave_delete(d3_tsave); d3_tsave = d3::tsave_new(env->get_string_arg(i->first, 1)); d3::align::set_tsave(d3_tsave); } else { assert(0); } } /* * Apply implication logic. */ if (extend == 0 && vise_count != 0) { implication::changed("VISP requires increased image extents.", "Image extension is now enabled.", "--extend"); extend = 1; } if (psf_match && ex_count) unsupported::fornow("PSF calibration with exclusion regions."); if (d3_output != NULL && ip_iterations != 0) unsupported::fornow("3D modeling with Irani-Peleg rendering"); #if 0 if (extend == 0 && d3_output != NULL) { implication::changed("3D modeling requires increased image extents.", "Image extension is now enabled.", "--extend"); extend = 1; } #endif #if 0 if (cx_parameter != 0 && !exposure_register) { implication::changed("Certainty-based rendering requires exposure registration.", "Exposure registration is now enabled.", "--exp-register"); d2::align::exp_register(); exposure_register = 1; } #endif /* * Set alignment class exclusion region static variables */ d2::align::set_exclusion(ex_parameters, ex_count); /* * Initialize renderer class statics. */ d2::render::render_init(ex_count, ex_parameters, ex_show, extend, scale_factor); /* * Set confidence */ d2::exposure::set_confidence(cx_parameter); /* * Keep transformations for Irani-Peleg, psf-match, and * VISE */ if (ip_iterations > 0 || psf_match || vise_count > 0) { d2::align::keep(); } /* * Initialize device-specific variables */ // int input_file_count = argc - i - 1; int input_file_count = files.size() - 1; d2::psf *device_response[psf_N] = { NULL, NULL }; d2::exposure **input_exposure = NULL; ale_pos view_angle = 43.7 * M_PI / 180; // ale_pos view_angle = 90 * M_PI / 180; input_exposure = (d2::exposure **) // malloc((argc - i - 1) * sizeof(d2::exposure *)); malloc(input_file_count * sizeof(d2::exposure *)); if (device != NULL) { if (!strcmp(device, "xvp610_640x480")) { device_response[psf_linear] = new xvp610_640x480::lpsf(); device_response[psf_nonlinear] = new xvp610_640x480::nlpsf(); for (int ii = 0; ii < input_file_count; ii++) input_exposure[ii] = new xvp610_640x480::exposure(); view_angle = xvp610_640x480::view_angle(); } else if (!strcmp(device, "xvp610_320x240")) { device_response[psf_linear] = new xvp610_320x240::lpsf(); device_response[psf_nonlinear] = new xvp610_320x240::nlpsf(); for (int ii = 0; ii < input_file_count; ii++) input_exposure[ii] = new xvp610_320x240::exposure(); view_angle = xvp610_320x240::view_angle(); } else if (!strcmp(device, "ov7620")) { device_response[psf_linear] = new ov7620_raw_linear::lpsf(); device_response[psf_nonlinear] = NULL; for (int ii = 0; ii < input_file_count; ii++) input_exposure[ii] = new ov7620_raw_linear::exposure(); d2::image_rw::set_default_bayer(IMAGE_BAYER_BGRG); } else if (!strcmp(device, "canon_300d")) { device_response[psf_linear] = new canon_300d_raw_linear::lpsf(); device_response[psf_nonlinear] = NULL; for (int ii = 0; ii < input_file_count; ii++) input_exposure[ii] = new canon_300d_raw_linear::exposure(); d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG); } else if (!strcmp(device, "nikon_d50")) { device_response[psf_linear] = nikon_d50::lpsf(); device_response[psf_nonlinear] = nikon_d50::nlpsf(); for (int ii = 0; ii < input_file_count; ii++) input_exposure[ii] = new nikon_d50::exposure(); d2::image_rw::set_default_bayer( nikon_d50::bayer() ); } else if (!strcmp(device, "canon_300d+85mm_1.8")) { device_response[psf_linear] = new canon_300d_raw_linear_85mm_1_8::lpsf(); device_response[psf_nonlinear] = NULL; for (int ii = 0; ii < input_file_count; ii++) input_exposure[ii] = new canon_300d_raw_linear_85mm_1_8::exposure(); d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG); view_angle = canon_300d_raw_linear_85mm_1_8::view_angle(); } else if (!strcmp(device, "canon_300d+50mm_1.8")) { device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_8::lpsf(); device_response[psf_nonlinear] = NULL; for (int ii = 0; ii < input_file_count; ii++) input_exposure[ii] = new canon_300d_raw_linear_50mm_1_8::exposure(); d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG); view_angle = canon_300d_raw_linear_50mm_1_8::view_angle(); } else if (!strcmp(device, "canon_300d+50mm_1.4")) { device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_4::lpsf(); device_response[psf_nonlinear] = NULL; for (int ii = 0; ii < input_file_count; ii++) input_exposure[ii] = new canon_300d_raw_linear_50mm_1_4::exposure(); d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG); view_angle = canon_300d_raw_linear_50mm_1_4::view_angle(); } else if (!strcmp(device, "canon_300d+50mm_1.4@1.4")) { device_response[psf_linear] = new canon_300d_raw_linear_50mm_1_4_1_4::lpsf(); device_response[psf_nonlinear] = NULL; for (int ii = 0; ii < input_file_count; ii++) input_exposure[ii] = new canon_300d_raw_linear_50mm_1_4_1_4::exposure(); d2::image_rw::set_default_bayer(IMAGE_BAYER_RGBG); view_angle = canon_300d_raw_linear_50mm_1_4_1_4::view_angle(); } else { ui::get()->unknown_device(device); } } else { for (int ii = 0; ii < input_file_count; ii++) input_exposure[ii] = new d2::exposure_default(); } /* * User-specified variables. */ if (user_view_angle != 0) { view_angle = user_view_angle; } if (user_bayer != IMAGE_BAYER_DEFAULT) { d2::image_rw::set_default_bayer(user_bayer); } /* * PSF-match exposure. */ if (psf_match) { delete input_exposure[input_file_count - 1]; input_exposure[input_file_count - 1] = new d2::exposure_default(); } /* * Initialize output exposure */ d2::exposure *output_exposure = new d2::exposure_default(); output_exposure->set_multiplier(exp_mult); /* * Configure the response function. */ d2::psf *response[2] = {NULL, NULL}; for (int n = 0; n < psf_N; n++ ) { if (psf[n] != NULL) { response[n] = d2::psf_parse::get((n == psf_linear), psf[n]); } else if (device_response[n] != NULL) { /* * Device-specific response */ response[n] = device_response[n]; } else { /* * Default point-spread function. */ if (n == psf_linear) { /* * Default lpsf is a box filter * of diameter 1.0 (radius * 0.5). */ response[n] = new d2::box(0.5); } else if (n == psf_nonlinear) { /* * nlpsf is disabled by default. */ response[n] = NULL; } } } /* * First file argument. Print general file information as well * as information specific to this argument. Initialize image * file handler. */ // d2::image_rw::init(argc - i - 1, argv + i, argv[argc - 1], input_exposure, output_exposure); // ochain_names[0] = argv[argc - 1]; const char **input_files = (const char **) malloc(sizeof(const char *) * input_file_count); for (int i = 0; i < input_file_count; i++) { input_files[i] = files[i].first; } d2::image_rw::init(input_file_count, input_files, files[files.size() - 1].first, input_exposure, output_exposure); ochain_names[0] = files[files.size() - 1].first; /* * Handle control point data for alignment */ d2::align::set_cp_count(d3::cpf::count()); for (unsigned int ii = 0; ii < d3::cpf::count(); ii++) d2::align::set_cp(ii, d3::cpf::get_2d(ii)); /* * PSF-match bayer patterns. */ if (psf_match) { // d2::image_rw::set_specific_bayer(argc - i - 2, IMAGE_BAYER_NONE); d2::image_rw::set_specific_bayer(input_file_count - 1, IMAGE_BAYER_NONE); } /* * Handle alignment weight map, if necessary */ if (wm_filename != NULL) { d2::image *weight_map; weight_map = d2::image_rw::read_image(wm_filename, new d2::exposure_linear()); weight_map->set_offset(wm_offsety, wm_offsetx); d2::align::set_weight_map(weight_map); } /* * Initialize alignment interpolant. */ if (strcmp(afilter_type, "internal")) d2::align::set_interpolant(d2::render_parse::get_SSF(afilter_type)); /* * Initialize achain and ochain. */ achain = d2::render_parse::get(achain_type); for (int chain = 0; chain < oc_count; chain++) ochain[chain] = d2::render_parse::get(ochain_types[chain]); /* * Use merged renderings as reference images in * alignment. */ d2::align::set_reference(achain); /* * Tell the alignment class about the scale factor. */ d2::align::set_scale(scale_factor); /* * Initialize visp. */ d2::vise_core::set_scale(vise_scale_factor); for (int opt = 0; opt < vise_count; opt++) { d2::vise_core::add(d2::render_parse::get(visp[opt * 4 + 0]), visp[opt * 4 + 1], visp[opt * 4 + 2], visp[opt * 4 + 3]); } /* * Initialize non-incremental renderers */ #if 0 if (usm_multiplier != 0) { /* * Unsharp Mask renderer */ ochain[0] = new d2::usm(ochain[0], scale_factor, usm_multiplier, inc, response[psf_linear], response[psf_nonlinear], &input_exposure[0]); } #endif if (psf_match) { /* * Point-spread function calibration renderer. * This renderer does not produce image output. * It is reserved for use with the point-spread * function calibration script * ale-psf-calibrate. */ ochain[0] = new d2::psf_calibrate(ochain[0], 1, inc, response[psf_linear], response[psf_nonlinear], psf_match_args); } else if (ip_iterations != 0) { /* * Irani-Peleg renderer */ ochain[0] = new d2::ipc( ochain[0], ip_iterations, inc, response[psf_linear], response[psf_nonlinear], (exposure_register == 1), ip_use_median, ipwl); } /* * Iterate through all files. */ for (unsigned int j = 0; j < d2::image_rw::count(); j++) { /* * Iterate through non-global options */ environment *env = files[j].second; for (std::map::iterator i = env->get_map().begin(); i != env->get_map().end(); i++) { if (!env->is_option(i->first)) continue; const char *option_name = env->get_option_name(i->first); if (!strcmp(option_name, "mc")) { d2::align::mc(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "md")) { d2::trans_multi::set_md(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "ma-cert")) { d2::align::set_ma_cert(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "mi")) { d2::trans_multi::set_mi(env->get_double_arg(i->first, 1)); } else if (!strcmp(option_name, "gs-mo")) { const char *option = env->get_string_arg(i->first, 1); double gs_mo; int characters; sscanf(option, "%lf%n", &gs_mo, &characters); if (*(option + characters) == '%') d2::align::gs_mo(gs_mo, 1); else d2::align::gs_mo(gs_mo, 0); } else if (!strcmp(option_name, "ev")) { double ev = env->get_double_arg(i->first, 1); double gain_value = pow(2, -ev); if (j == 0) d2::exposure::set_gain_reference(gain_value); else input_exposure[j]->set_gain_multiplier( (double) d2::exposure::get_gain_reference() / gain_value); } else if (!strcmp(option_name, "black")) { double black = env->get_double_arg(i->first, 1); input_exposure[j]->set_black_level(black); } else if (!strcmp(option_name, "perturb-upper")) { const char *option = env->get_string_arg(i->first, 1); double perturb_upper; int characters; sscanf(option, "%lf%n", &perturb_upper, &characters); if (*(option + characters) == '%') d2::align::set_perturb_upper(perturb_upper, 1); else d2::align::set_perturb_upper(perturb_upper, 0); } else if (!strcmp(option_name, "threads")) { thread::set_count((unsigned int) env->get_int_arg(i->first, 1)); } else if (!strcmp(option_name, "per-cpu")) { thread::set_per_cpu((unsigned int) env->get_int_arg(i->first, 1)); } else { /* * This error should be encountered earlier. */ assert(0); fprintf(stderr, "\n\nError: option `%s' must be applied globally.", option_name); fprintf(stderr, "\n\nHint: Move option `%s' prior to file and scope operators.\n\n", option_name); exit(1); } } if (j == 0) { /* * Write comment information about original frame and * target image to the transformation save file, if we * have one. */ const d2::image *im = d2::image_rw::open(0); // tsave_orig(tsave, argv[i], im->avg_channel_magnitude()); // tsave_target(tsave, argv[argc - 1]); tsave_orig(tsave, files[0].first, im->avg_channel_magnitude()); tsave_target(tsave, files[files.size() - 1].first); d2::image_rw::close(0); /* * Handle the original frame. */ // ui::get()->original_frame_start(argv[i]); ui::get()->original_frame_start(files[0].first); for (int opt = 0; opt < oc_count; opt++) { ui::get()->set_orender_current(opt); ochain[opt]->sync(0); if (inc) { ui::get()->writing_output(opt); d2::image_rw::write_image(ochain_names[opt], ochain[opt]->get_image(0)); } } d2::vise_core::frame_queue_add(0); ui::get()->original_frame_done(); continue; } /* * Handle supplemental frames. */ const char *name = d2::image_rw::name(j); ui::get()->supplemental_frame_start(name); /* * Write comment information about the * supplemental frame to the transformation * save file, if we have one. */ tsave_info (tsave, name); const d2::image *im = d2::image_rw::open(j); d2::pixel apm = im->avg_channel_magnitude(); tsave_apm(tsave, apm[0], apm[1], apm[2]); d2::image_rw::close(j); for (int opt = 0; opt < oc_count; opt++) { ui::get()->set_orender_current(opt); ochain[opt]->sync(j); if (inc) { ui::get()->writing_output(opt); d2::image_rw::write_image(ochain_names[opt], ochain[opt]->get_image(j)); } } d2::vise_core::frame_queue_add(j); ui::get()->supplemental_frame_done(); } /* * Do any post-processing and output final image * * XXX: note that the Irani-Peleg renderer currently * returns zero for ochain[0]->sync(), since it writes * output internally when inc != 0. * * XXX: Leave ochain[0] last, since this may allow disposal of * rendering structures not required by the Irani-Peleg * renderer. */ for (int opt = 1; opt < oc_count; opt++) if ((ochain[opt]->sync() || !inc) && !psf_match) { ui::get()->writing_output(opt); d2::image_rw::write_image(ochain_names[opt], ochain[opt]->get_image()); } if (oc_count > 0) if ((ochain[0]->sync() || !inc) && !psf_match) { ui::get()->writing_output(0); d2::image_rw::write_image(ochain_names[0], ochain[0]->get_image()); } /* * Output a summary match statistic. */ ui::get()->ale_2d_done((double) d2::align::match_summary()); /* * Perform any 3D tasks */ optimizations::begin_3d_work(); if (d3_count > 0) { ui::get()->d3_start(); d3::align::init_angle(view_angle); ui::get()->d3_init_view_angle((double) view_angle / M_PI * 180); d3::align::init_from_d2(); if (d3::cpf::count() > 0) { ui::get()->d3_control_point_solve(); d3::cpf::solve_3d(); ui::get()->d3_control_point_solve_done(); } ui::get()->d3_final_view_angle(d3::align::angle_of(0) / M_PI * 180); d3::align::write_alignments(); d3::scene::set_filter_type(d3chain_type); d3::scene::init_from_d2(); ui::get()->d3_subdividing_space(); d3::scene::make_space(d3_depth, d3_output, &d3_depth_pt, &d3_output_pt); ui::get()->d3_subdividing_space_done(); ui::get()->d3_updating_occupancy(); d3::scene::reduce_cost_to_search_depth(output_exposure, inc); ui::get()->d3_updating_occupancy_done(); d3::scene::d3px(d3px_count, d3px_parameters); int view_count = 0; for (unsigned int i = 0; i < d2::image_rw::count(); i++) { assert (i < d3_count); if (d3_depth[i] != NULL) { ui::get()->d3_writing_output(d3_depth[i]); ui::get()->d3_render_status(0, 0, -1, -1, -1, -1, 0); const d2::image *im = d3::scene::depth(i); d2::image_rw::write_image(d3_depth[i], im, output_exposure, 1, 1); delete im; ui::get()->d3_writing_output_done(); } if (d3_output[i] != NULL) { ui::get()->d3_writing_output(d3_output[i]); const d2::image *im = d3::scene::view(i); d2::image_rw::write_image(d3_output[i], im, output_exposure); delete im; d3::focus::set_camera(view_count++); ui::get()->d3_writing_output_done(); } for (std::map::iterator i = d3_output_pt.begin(); i != d3_output_pt.end(); i++) { ui::get()->d3_writing_output(i->first); const d2::image *im = d3::scene::view(i->second); d2::image_rw::write_image(i->first, im, output_exposure); delete im; d3::focus::set_camera(view_count++); ui::get()->d3_writing_output_done(); } for (std::map::iterator i = d3_depth_pt.begin(); i != d3_depth_pt.end(); i++) { ui::get()->d3_writing_output(i->first); ui::get()->d3_render_status(0, 0, -1, -1, -1, -1, 0); const d2::image *im = d3::scene::depth(i->second); d2::image_rw::write_image(i->first, im, output_exposure, 1, 1); delete im; ui::get()->d3_writing_output_done(); } } for (unsigned int i = d2::image_rw::count(); i < d3_count; i++) { if (d3_depth[i] != NULL) { fprintf(stderr, "\n\n*** Frame number for --3dd too high. ***\n\n"); } if (d3_output[i] != NULL) { fprintf(stderr, "\n\n*** Frame number for --3dv too high. ***\n\n"); } } } /* * Destroy the image file handler */ d2::image_rw::destroy(); /* * Delete the transformation file structures, if any * exist. */ tsave_delete(tsave); tload_delete(tload); /* * We're done. */ exit(0); } }; #endif