d2/align: Migrate code (indicated as broken by GCC) to Libale.
[Ale.git] / d3 / tfile.h
blob4c423e3e979dfcd1777f7c3b2a10a20a964065b5
1 // Copyright 2002, 2003, 2005 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 3 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 * d3/tfile.h: Read and write 3D transformation data files.
26 * This version of ALE reads and writes version 0 3D transformation data files.
29 #ifndef __d3tfile_h__
30 #define __d3tfile_h__
32 #include "pt.h"
34 #define D3_TFILE_VERSION 0
35 #define D3_TFILE_VERSION_MAX 0
37 extern int tfile_input_version;
38 extern int tfile_output_version;
41 * Structure to describe a transformation data file to load data from.
44 struct tload_t {
45 const char *filename;
46 FILE *file;
50 * Structure to describe a transformation data file to write data to.
53 struct tsave_t {
54 const char *filename;
55 const char *target;
56 const char *orig;
57 FILE *file;
61 * Create a new tload_t transformation data file structure, used for
62 * reading data from transformation data files.
65 static inline struct tload_t *tload_new(const char *filename) {
66 FILE *file = fopen (filename, "r");
67 struct tload_t *result = NULL;
69 if (!file) {
70 fprintf(stderr, "tload: Error: could not open transformation data file '%s'.", filename);
71 exit(1);
74 result = (struct tload_t *)
75 malloc(sizeof(struct tload_t));
76 result->filename = filename;
77 result->file = file;
79 return result;
83 * Load the first transformation from a transformation data file associated with
84 * transformation data file structure T, or return the default transformation
85 * if no transformation is available.
87 * T is a pointer to the tload_t transformation data file structure.
89 * DEFAULT_TRANSFORM is the default transformation result.
91 * IS_DEFAULT is used to signal a non-default transformation result.
94 static inline pt tload_first(struct tload_t *t,
95 pt default_transform, int *is_default) {
97 pt result = default_transform;
99 *is_default = 1;
102 * If there is no file, return the default.
105 if (t == NULL)
106 return result;
109 * Search through the initial part of the file to determine
110 * its version.
114 * Skip comments
117 int first_character;
119 first_character = fgetc(t->file);
121 while (first_character == ' '
122 || first_character == 0xa
123 || first_character == 0xd
124 || first_character == '\t'
125 || first_character == '#') {
126 ungetc(first_character, t->file);
127 char line[1024];
128 char *fgets_result = fgets(line, 1024, t->file);
130 assert(fgets_result);
132 if (strlen(line) >= 1023) {
133 fprintf(stderr,
134 "\n3d-trans-load: Error: line too long in input file\n");
135 exit(1);
138 first_character = fgetc(t->file);
141 if (first_character != EOF)
142 ungetc(first_character, t->file);
144 if (first_character != 'W') {
145 fprintf(stderr, "\n3d-trans-load: First command must be a version number.\n");
146 exit(1);
150 * Obtain version from version command string.
153 char line[1024];
154 char *fgets_result = fgets(line, 1024, t->file);
156 assert(fgets_result);
158 if (strlen(line) >= 1023) {
159 fprintf(stderr,
160 "\n3d-trans-load: Error: line too long in input file\n");
161 exit(1);
164 int count = sscanf(line, "W %d", &tfile_input_version);
166 if (count < 1) {
167 fprintf(stderr, "Error in 3d transformation "
168 "file version command.\n");
169 exit(1);
170 } else if (tfile_input_version > D3_TFILE_VERSION_MAX) {
171 fprintf(stderr, "Unsupported 3D transformation "
172 "file version %d\n",
173 tfile_input_version);
174 exit(1);
178 * Read each line of the file until we find a transformation
179 * or EOF.
182 while (!feof(t->file)) {
183 char line[1024];
185 if (!fgets(line, 1024, t->file))
186 return result;
188 if (strlen(line) >= 1023) {
189 fprintf(stderr,
190 "\ntrans-load: Error: line too long in input file\n");
191 exit(1);
194 const double rtod_multiplier = 180 / M_PI;
196 switch (line[0]) {
197 case ' ':
198 case 0xa:
199 case 0xd:
200 case '\t':
201 case '#':
202 /* Comment or whitespace */
203 break;
204 case 'D':
205 case 'd':
206 /* Default transformation */
207 return result;
208 case 'V':
209 case 'v':
210 unsigned int count;
211 double view_angle;
213 count = sscanf(line, "V %lf", &view_angle);
215 if (count < 1) {
216 fprintf(stderr, "\n3d-trans-load: Error: "
217 "Malformed 'V' command.\n");
218 exit(1);
221 result.view_angle(view_angle / rtod_multiplier);
223 break;
224 case 'E':
225 case 'e':
226 /* Euclidean transformation data */
227 *is_default = 0;
229 double width, height;
230 double values[6] = {0, 0, -1, 0, 0, 0};
231 int count;
233 count = sscanf(line, "E %lf%lf%lf%lf%lf%lf%lf%lf",
234 &width, &height,
235 &values[1], &values[0], &values[2],
236 &values[4], &values[3], &values[5]);
238 if (count < 8)
239 fprintf(stderr, "\n3d-trans-load: warning: "
240 "Missing args for 'E'\n");
242 if (width != result.scaled_width()
243 || height != result.scaled_height()) {
244 fprintf(stderr, "\n3d-trans-load: Error: "
245 "Scaled image width and/or height mismatch.");
248 for (int i = 3; i < 6; i++) {
249 values [i] /= rtod_multiplier;
252 result.e().set(values);
254 return result;
256 break;
257 default:
258 fprintf(stderr,
259 "\ntrans-load: Error in tload_first: unrecognized command '%s'\n",
260 line);
261 exit(1);
266 * EOF reached: return default transformation.
269 return result;
273 * Load the next transformation from a transformation data file associated with
274 * transformation data file structure T, or return the default transformation
275 * if no transformation is available.
277 * T is a pointer to the tload_t transformation data file structure.
279 * IS_P is nonzero if a projective transformation is expected.
281 * DEFAULT_TRANSFORM is the default transformation result.
283 * IS_DEFAULT is used to signal a non-default transformation result.
286 static inline pt tload_next(struct tload_t *t,
287 pt default_transform, int *is_default) {
289 pt result = default_transform;
291 *is_default = 1;
294 * Read each line of the file until we find a transformation.
297 while (t && !feof(t->file)) {
298 char line[1024];
300 if (!fgets(line, 1024, t->file))
301 return result;
303 if (strlen(line) >= 1023) {
304 fprintf(stderr,
305 "\ntrans-load: warning: line too long in input file\n");
308 const double rtod_multiplier = 180 / M_PI;
310 switch (line[0]) {
311 case ' ':
312 case 0xa:
313 case 0xd:
314 case '\t':
315 case '#':
316 /* Comment or whitespace */
317 break;
318 case 'D':
319 case 'd':
320 /* Default transformation */
321 return result;
322 case 'V':
323 case 'v':
324 unsigned int count;
325 double view_angle;
327 count = sscanf(line, "V %lf", &view_angle);
329 if (count < 1) {
330 fprintf(stderr, "\n3d-trans-load: Error: "
331 "Malformed 'V' command.\n");
332 exit(1);
335 result.view_angle(view_angle / rtod_multiplier);
337 break;
338 case 'E':
339 case 'e':
340 /* Euclidean transformation data */
341 *is_default = 0;
343 double width, height;
344 double values[6] = {0, 0, -1, 0, 0, 0};
345 int count;
347 count = sscanf(line, "E %lf%lf%lf%lf%lf%lf%lf%lf",
348 &width, &height,
349 &values[1], &values[0], &values[2],
350 &values[4], &values[3], &values[5]);
352 if (count < 8)
353 fprintf(stderr, "\n3d-trans-load: warning: "
354 "Missing args for 'E'\n");
356 if (width != result.scaled_width()
357 || height != result.scaled_height()) {
358 fprintf(stderr, "\n3d-trans-load: Error: "
359 "Scaled image width and/or height mismatch.");
362 for (int i = 3; i < 6; i++) {
363 values [i] /= rtod_multiplier;
366 result.e().set(values);
368 return result;
370 break;
371 default:
372 fprintf(stderr,
373 "\ntrans-load: Error in tload_next: unrecognized command '%s'\n",
374 line);
375 exit(1);
379 return result;
383 * Create a new tsave_t transformation data file structure, used for
384 * writing data to transformation data files.
387 static inline struct tsave_t *tsave_new(const char *filename) {
388 FILE *file = fopen (filename, "w");
389 struct tsave_t *result = NULL;
391 if (!file) {
392 fprintf(stderr, "tsave: Error: could not open transformation data file '%s'.", filename);
393 exit(1);
396 result = (struct tsave_t *)
397 malloc(sizeof(struct tsave_t));
398 result->filename = filename;
399 result->file = file;
400 result->orig = "unknown";
401 result->target = "unknown";
403 fprintf(file, "# created by ALE 3D transformation file handler version %d\n",
404 D3_TFILE_VERSION);
406 fclose(file);
408 return result;
412 * Save the first transformation to a transformation data file associated with
413 * transformation data file structure T, or do nothing if T is NULL. This
414 * function also establishes the output file version.
416 * OFFSET is the transformation to be saved.
418 * IS_PROJECTIVE indicates whether to write a projective transformation.
422 static inline void tsave_first(struct tsave_t *t, pt offset) {
424 if (t == NULL)
425 return;
427 t->file = fopen(t->filename, "a");
429 tfile_output_version = 0;
431 fprintf(t->file, "# producing 3D transformation file syntax version %d\n", tfile_output_version);
432 fprintf(t->file, "W %d\n", tfile_output_version);
434 // fprintf(t->file, "# Comment: Target output file is %s\n", t->target);
435 // fprintf(t->file, "# Comment: Original frame is %s\n", t->orig);
437 const double rtod_multiplier = 180 / M_PI;
439 fprintf(t->file, "V %lf\n", (double) offset.view_angle() * rtod_multiplier);
441 fprintf(t->file, "E ");
442 fprintf(t->file, "%f %f ", (double) offset.scaled_width(), (double) offset.scaled_height());
443 fprintf(t->file, "%f ", (double) offset.e().get_translation(1));
444 fprintf(t->file, "%f ", (double) offset.e().get_translation(0));
445 fprintf(t->file, "%f ", (double) offset.e().get_translation(2));
446 fprintf(t->file, "%f ", (double) offset.e().get_rotation(1) * rtod_multiplier);
447 fprintf(t->file, "%f ", (double) offset.e().get_rotation(0) * rtod_multiplier);
448 fprintf(t->file, "%f ", (double) offset.e().get_rotation(2) * rtod_multiplier);
450 fprintf(t->file, "\n");
452 fclose(t->file);
456 * Save the next transformation to a transformation data file associated with
457 * transformation data file structure T, or do nothing if T is NULL.
459 * OFFSET is the transformation to be saved.
461 * IS_PROJECTIVE indicates whether to write a projective transformation.
465 static inline void tsave_next(struct tsave_t *t, pt offset) {
467 if (t == NULL)
468 return;
470 t->file = fopen(t->filename, "a");
472 const double rtod_multiplier = 180 / M_PI;
474 fprintf(t->file, "V %lf\n", (double) offset.view_angle() * rtod_multiplier);
476 fprintf(t->file, "E ");
477 fprintf(t->file, "%f %f ", (double) offset.scaled_width(), (double) offset.scaled_height());
478 fprintf(t->file, "%f ", (double) offset.e().get_translation(1));
479 fprintf(t->file, "%f ", (double) offset.e().get_translation(0));
480 fprintf(t->file, "%f ", (double) offset.e().get_translation(2));
481 fprintf(t->file, "%f ", (double) offset.e().get_rotation(1) * rtod_multiplier);
482 fprintf(t->file, "%f ", (double) offset.e().get_rotation(0) * rtod_multiplier);
483 fprintf(t->file, "%f ", (double) offset.e().get_rotation(2) * rtod_multiplier);
485 fprintf(t->file, "\n");
487 fclose(t->file);
491 * Write information to a transformation file indicating the target output
492 * file.
495 static inline void tsave_target(struct tsave_t *t, const char *filename) {
496 if (t == NULL)
497 return;
499 t->target = filename;
500 if (t != NULL) {
501 t->file = fopen(t->filename, "a");
504 fclose(t->file);
509 * Write information to a transformation data file indicating the filename
510 * of the original frame (i.e. the first frame in the sequence of input
511 * frames).
514 static inline void tsave_orig(struct tsave_t *t, const char *filename) {
515 if (t == NULL)
516 return;
518 t->orig = filename;
522 * Write information to a transformation data file indicating the filename
523 * of a supplemental frame (i.e. a frame in the sequence of input frames
524 * that is not the first frame).
527 static inline void tsave_info(struct tsave_t *t, const char *filename) {
528 if (t != NULL) {
529 t->file = fopen(t->filename, "a");
531 fprintf(t->file, "# Comment: Supplemental frame %s\n", filename);
533 fclose(t->file);
538 * Write information to a transformation data file indicating the tonal
539 * registration multiplier.
542 static inline void tsave_trm(struct tsave_t *t, ale_real r, ale_real g, ale_real b) {
543 if (t != NULL) {
544 t->file = fopen(t->filename, "a");
546 fprintf(t->file, "# Comment: Exposure [r=%f g=%f b=%f]\n", (double) r, (double) g, (double) b);
548 fclose(t->file);
553 * Write information to a transformation data file indicating the average
554 * pixel magnitude.
557 static inline void tsave_apm(struct tsave_t *t, ale_real r, ale_real g, ale_real b) {
558 if (t != NULL) {
559 t->file = fopen(t->filename, "a");
561 fprintf(t->file, "# Comment: Avg magnitude [r=%f g=%f b=%f]\n", (double) r, (double) g, (double) b);
563 fclose(t->file);
569 * Destroy a tload_t transformation data file structure.
572 static inline void tload_delete(struct tload_t *victim) {
573 if (victim)
574 fclose(victim->file);
575 free(victim);
579 * Destroy a tsave_t transformation data file structure.
582 static inline void tsave_delete(struct tsave_t *victim) {
583 free(victim);
586 #endif