// Copyright 2002, 2003, 2005 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 */ /* * d3/tfile.h: Read and write 3D transformation data files. */ /* * This version of ALE reads and writes version 0 3D transformation data files. */ #ifndef __d3tfile_h__ #define __d3tfile_h__ #include "pt.h" #define D3_TFILE_VERSION 0 #define D3_TFILE_VERSION_MAX 0 extern int tfile_input_version; extern int tfile_output_version; /* * Structure to describe a transformation data file to load data from. */ struct tload_t { const char *filename; FILE *file; }; /* * Structure to describe a transformation data file to write data to. */ struct tsave_t { const char *filename; const char *target; const char *orig; FILE *file; }; /* * Create a new tload_t transformation data file structure, used for * reading data from transformation data files. */ static inline struct tload_t *tload_new(const char *filename) { FILE *file = fopen (filename, "r"); struct tload_t *result = NULL; if (!file) { fprintf(stderr, "tload: Error: could not open transformation data file '%s'.", filename); exit(1); } result = (struct tload_t *) malloc(sizeof(struct tload_t)); result->filename = filename; result->file = file; return result; } /* * Load the first transformation from a transformation data file associated with * transformation data file structure T, or return the default transformation * if no transformation is available. * * T is a pointer to the tload_t transformation data file structure. * * DEFAULT_TRANSFORM is the default transformation result. * * IS_DEFAULT is used to signal a non-default transformation result. */ static inline pt tload_first(struct tload_t *t, pt default_transform, int *is_default) { pt result = default_transform; *is_default = 1; /* * If there is no file, return the default. */ if (t == NULL) return result; /* * Search through the initial part of the file to determine * its version. */ /* * Skip comments */ int first_character; first_character = fgetc(t->file); while (first_character == ' ' || first_character == 0xa || first_character == 0xd || first_character == '\t' || first_character == '#') { ungetc(first_character, t->file); char line[1024]; fgets(line, 1024, t->file); if (strlen(line) >= 1023) { fprintf(stderr, "\n3d-trans-load: Error: line too long in input file\n"); exit(1); } first_character = fgetc(t->file); } if (first_character != EOF) ungetc(first_character, t->file); if (first_character != 'W') { fprintf(stderr, "\n3d-trans-load: First command must be a version number.\n"); exit(1); } /* * Obtain version from version command string. */ char line[1024]; fgets(line, 1024, t->file); if (strlen(line) >= 1023) { fprintf(stderr, "\n3d-trans-load: Error: line too long in input file\n"); exit(1); } int count = sscanf(line, "W %d", &tfile_input_version); if (count < 1) { fprintf(stderr, "Error in 3d transformation " "file version command.\n"); exit(1); } else if (tfile_input_version > D3_TFILE_VERSION_MAX) { fprintf(stderr, "Unsupported 3D transformation " "file version %d\n", tfile_input_version); exit(1); } /* * Read each line of the file until we find a transformation * or EOF. */ while (!feof(t->file)) { char line[1024]; fgets(line, 1024, t->file); if (feof(t->file)) return result; if (strlen(line) >= 1023) { fprintf(stderr, "\ntrans-load: Error: line too long in input file\n"); exit(1); } const double rtod_multiplier = 180 / M_PI; switch (line[0]) { case ' ': case 0xa: case 0xd: case '\t': case '#': /* Comment or whitespace */ break; case 'D': case 'd': /* Default transformation */ return result; case 'V': case 'v': unsigned int count; double view_angle; count = sscanf(line, "V %lf", &view_angle); if (count < 1) { fprintf(stderr, "\n3d-trans-load: Error: " "Malformed 'V' command.\n"); exit(1); } result.view_angle(view_angle / rtod_multiplier); break; case 'E': case 'e': /* Euclidean transformation data */ *is_default = 0; { double width, height; double values[6] = {0, 0, -1, 0, 0, 0}; int count; count = sscanf(line, "E %lf%lf%lf%lf%lf%lf%lf%lf", &width, &height, &values[1], &values[0], &values[2], &values[4], &values[3], &values[5]); if (count < 8) fprintf(stderr, "\n3d-trans-load: warning: " "Missing args for 'E'\n"); if (width != result.scaled_width() || height != result.scaled_height()) { fprintf(stderr, "\n3d-trans-load: Error: " "Scaled image width and/or height mismatch."); } for (int i = 3; i < 6; i++) { values [i] /= rtod_multiplier; } result.e().set(values); return result; } break; default: fprintf(stderr, "\ntrans-load: Error in tload_first: unrecognized command '%s'\n", line); exit(1); } } /* * EOF reached: return default transformation. */ return result; } /* * Load the next transformation from a transformation data file associated with * transformation data file structure T, or return the default transformation * if no transformation is available. * * T is a pointer to the tload_t transformation data file structure. * * IS_P is nonzero if a projective transformation is expected. * * DEFAULT_TRANSFORM is the default transformation result. * * IS_DEFAULT is used to signal a non-default transformation result. */ static inline pt tload_next(struct tload_t *t, pt default_transform, int *is_default) { pt result = default_transform; *is_default = 1; /* * Read each line of the file until we find a transformation. */ while (t && !feof(t->file)) { char line[1024]; fgets(line, 1024, t->file); if (feof(t->file)) return result; if (strlen(line) >= 1023) { fprintf(stderr, "\ntrans-load: warning: line too long in input file\n"); } const double rtod_multiplier = 180 / M_PI; switch (line[0]) { case ' ': case 0xa: case 0xd: case '\t': case '#': /* Comment or whitespace */ break; case 'D': case 'd': /* Default transformation */ return result; case 'V': case 'v': unsigned int count; double view_angle; count = sscanf(line, "V %lf", &view_angle); if (count < 1) { fprintf(stderr, "\n3d-trans-load: Error: " "Malformed 'V' command.\n"); exit(1); } result.view_angle(view_angle / rtod_multiplier); break; case 'E': case 'e': /* Euclidean transformation data */ *is_default = 0; { double width, height; double values[6] = {0, 0, -1, 0, 0, 0}; int count; count = sscanf(line, "E %lf%lf%lf%lf%lf%lf%lf%lf", &width, &height, &values[1], &values[0], &values[2], &values[4], &values[3], &values[5]); if (count < 8) fprintf(stderr, "\n3d-trans-load: warning: " "Missing args for 'E'\n"); if (width != result.scaled_width() || height != result.scaled_height()) { fprintf(stderr, "\n3d-trans-load: Error: " "Scaled image width and/or height mismatch."); } for (int i = 3; i < 6; i++) { values [i] /= rtod_multiplier; } result.e().set(values); return result; } break; default: fprintf(stderr, "\ntrans-load: Error in tload_next: unrecognized command '%s'\n", line); exit(1); } } return result; } /* * Create a new tsave_t transformation data file structure, used for * writing data to transformation data files. */ static inline struct tsave_t *tsave_new(const char *filename) { FILE *file = fopen (filename, "w"); struct tsave_t *result = NULL; if (!file) { fprintf(stderr, "tsave: Error: could not open transformation data file '%s'.", filename); exit(1); } result = (struct tsave_t *) malloc(sizeof(struct tsave_t)); result->filename = filename; result->file = file; result->orig = "unknown"; result->target = "unknown"; fprintf(file, "# created by ALE 3D transformation file handler version %d\n", D3_TFILE_VERSION); fclose(file); return result; } /* * Save the first transformation to a transformation data file associated with * transformation data file structure T, or do nothing if T is NULL. This * function also establishes the output file version. * * OFFSET is the transformation to be saved. * * IS_PROJECTIVE indicates whether to write a projective transformation. * */ static inline void tsave_first(struct tsave_t *t, pt offset) { if (t == NULL) return; t->file = fopen(t->filename, "a"); tfile_output_version = 0; fprintf(t->file, "# producing 3D transformation file syntax version %d\n", tfile_output_version); fprintf(t->file, "W %d\n", tfile_output_version); // fprintf(t->file, "# Comment: Target output file is %s\n", t->target); // fprintf(t->file, "# Comment: Original frame is %s\n", t->orig); const double rtod_multiplier = 180 / M_PI; fprintf(t->file, "V %lf\n", (double) offset.view_angle() * rtod_multiplier); fprintf(t->file, "E "); fprintf(t->file, "%f %f ", (double) offset.scaled_width(), (double) offset.scaled_height()); fprintf(t->file, "%f ", (double) offset.e().get_translation(1)); fprintf(t->file, "%f ", (double) offset.e().get_translation(0)); fprintf(t->file, "%f ", (double) offset.e().get_translation(2)); fprintf(t->file, "%f ", (double) offset.e().get_rotation(1) * rtod_multiplier); fprintf(t->file, "%f ", (double) offset.e().get_rotation(0) * rtod_multiplier); fprintf(t->file, "%f ", (double) offset.e().get_rotation(2) * rtod_multiplier); fprintf(t->file, "\n"); fclose(t->file); } /* * Save the next transformation to a transformation data file associated with * transformation data file structure T, or do nothing if T is NULL. * * OFFSET is the transformation to be saved. * * IS_PROJECTIVE indicates whether to write a projective transformation. * */ static inline void tsave_next(struct tsave_t *t, pt offset) { if (t == NULL) return; t->file = fopen(t->filename, "a"); const double rtod_multiplier = 180 / M_PI; fprintf(t->file, "V %lf\n", (double) offset.view_angle() * rtod_multiplier); fprintf(t->file, "E "); fprintf(t->file, "%f %f ", (double) offset.scaled_width(), (double) offset.scaled_height()); fprintf(t->file, "%f ", (double) offset.e().get_translation(1)); fprintf(t->file, "%f ", (double) offset.e().get_translation(0)); fprintf(t->file, "%f ", (double) offset.e().get_translation(2)); fprintf(t->file, "%f ", (double) offset.e().get_rotation(1) * rtod_multiplier); fprintf(t->file, "%f ", (double) offset.e().get_rotation(0) * rtod_multiplier); fprintf(t->file, "%f ", (double) offset.e().get_rotation(2) * rtod_multiplier); fprintf(t->file, "\n"); fclose(t->file); } /* * Write information to a transformation file indicating the target output * file. */ static inline void tsave_target(struct tsave_t *t, const char *filename) { if (t == NULL) return; t->target = filename; if (t != NULL) { t->file = fopen(t->filename, "a"); fclose(t->file); } } /* * Write information to a transformation data file indicating the filename * of the original frame (i.e. the first frame in the sequence of input * frames). */ static inline void tsave_orig(struct tsave_t *t, const char *filename) { if (t == NULL) return; t->orig = filename; } /* * Write information to a transformation data file indicating the filename * of a supplemental frame (i.e. a frame in the sequence of input frames * that is not the first frame). */ static inline void tsave_info(struct tsave_t *t, const char *filename) { if (t != NULL) { t->file = fopen(t->filename, "a"); fprintf(t->file, "# Comment: Supplemental frame %s\n", filename); fclose(t->file); } } /* * Write information to a transformation data file indicating the tonal * registration multiplier. */ static inline void tsave_trm(struct tsave_t *t, ale_real r, ale_real g, ale_real b) { if (t != NULL) { t->file = fopen(t->filename, "a"); fprintf(t->file, "# Comment: Exposure [r=%f g=%f b=%f]\n", (double) r, (double) g, (double) b); fclose(t->file); } } /* * Write information to a transformation data file indicating the average * pixel magnitude. */ static inline void tsave_apm(struct tsave_t *t, ale_real r, ale_real g, ale_real b) { if (t != NULL) { t->file = fopen(t->filename, "a"); fprintf(t->file, "# Comment: Avg magnitude [r=%f g=%f b=%f]\n", (double) r, (double) g, (double) b); fclose(t->file); } } /* * Destroy a tload_t transformation data file structure. */ static inline void tload_delete(struct tload_t *victim) { if (victim) fclose(victim->file); free(victim); } /* * Destroy a tsave_t transformation data file structure. */ static inline void tsave_delete(struct tsave_t *victim) { free(victim); } #endif