Changelog: Add credits for multithreading change.
[Ale.git] / d3 / tfile.h
blobad0bd6d40c3b6ecf258830940ecfa455b2ac898a
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 2 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * 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 fgets(line, 1024, t->file);
129 if (strlen(line) >= 1023) {
130 fprintf(stderr,
131 "\n3d-trans-load: Error: line too long in input file\n");
132 exit(1);
135 first_character = fgetc(t->file);
138 if (first_character != EOF)
139 ungetc(first_character, t->file);
141 if (first_character != 'W') {
142 fprintf(stderr, "\n3d-trans-load: First command must be a version number.\n");
143 exit(1);
147 * Obtain version from version command string.
150 char line[1024];
151 fgets(line, 1024, t->file);
152 if (strlen(line) >= 1023) {
153 fprintf(stderr,
154 "\n3d-trans-load: Error: line too long in input file\n");
155 exit(1);
158 int count = sscanf(line, "W %d", &tfile_input_version);
160 if (count < 1) {
161 fprintf(stderr, "Error in 3d transformation "
162 "file version command.\n");
163 exit(1);
164 } else if (tfile_input_version > D3_TFILE_VERSION_MAX) {
165 fprintf(stderr, "Unsupported 3D transformation "
166 "file version %d\n",
167 tfile_input_version);
168 exit(1);
172 * Read each line of the file until we find a transformation
173 * or EOF.
176 while (!feof(t->file)) {
177 char line[1024];
179 fgets(line, 1024, t->file);
181 if (feof(t->file))
182 return result;
184 if (strlen(line) >= 1023) {
185 fprintf(stderr,
186 "\ntrans-load: Error: line too long in input file\n");
187 exit(1);
190 const double rtod_multiplier = 180 / M_PI;
192 switch (line[0]) {
193 case ' ':
194 case 0xa:
195 case 0xd:
196 case '\t':
197 case '#':
198 /* Comment or whitespace */
199 break;
200 case 'D':
201 case 'd':
202 /* Default transformation */
203 return result;
204 case 'V':
205 case 'v':
206 unsigned int count;
207 double view_angle;
209 count = sscanf(line, "V %lf", &view_angle);
211 if (count < 1) {
212 fprintf(stderr, "\n3d-trans-load: Error: "
213 "Malformed 'V' command.\n");
214 exit(1);
217 result.view_angle(view_angle / rtod_multiplier);
219 break;
220 case 'E':
221 case 'e':
222 /* Euclidean transformation data */
223 *is_default = 0;
225 double width, height;
226 double values[6] = {0, 0, -1, 0, 0, 0};
227 int count;
229 count = sscanf(line, "E %lf%lf%lf%lf%lf%lf%lf%lf",
230 &width, &height,
231 &values[1], &values[0], &values[2],
232 &values[4], &values[3], &values[5]);
234 if (count < 8)
235 fprintf(stderr, "\n3d-trans-load: warning: "
236 "Missing args for 'E'\n");
238 if (width != result.scaled_width()
239 || height != result.scaled_height()) {
240 fprintf(stderr, "\n3d-trans-load: Error: "
241 "Scaled image width and/or height mismatch.");
244 for (int i = 3; i < 6; i++) {
245 values [i] /= rtod_multiplier;
248 result.e().set(values);
250 return result;
252 break;
253 default:
254 fprintf(stderr,
255 "\ntrans-load: Error in tload_first: unrecognized command '%s'\n",
256 line);
257 exit(1);
262 * EOF reached: return default transformation.
265 return result;
269 * Load the next transformation from a transformation data file associated with
270 * transformation data file structure T, or return the default transformation
271 * if no transformation is available.
273 * T is a pointer to the tload_t transformation data file structure.
275 * IS_P is nonzero if a projective transformation is expected.
277 * DEFAULT_TRANSFORM is the default transformation result.
279 * IS_DEFAULT is used to signal a non-default transformation result.
282 static inline pt tload_next(struct tload_t *t,
283 pt default_transform, int *is_default) {
285 pt result = default_transform;
287 *is_default = 1;
290 * Read each line of the file until we find a transformation.
293 while (t && !feof(t->file)) {
294 char line[1024];
296 fgets(line, 1024, t->file);
298 if (feof(t->file))
299 return result;
301 if (strlen(line) >= 1023) {
302 fprintf(stderr,
303 "\ntrans-load: warning: line too long in input file\n");
306 const double rtod_multiplier = 180 / M_PI;
308 switch (line[0]) {
309 case ' ':
310 case 0xa:
311 case 0xd:
312 case '\t':
313 case '#':
314 /* Comment or whitespace */
315 break;
316 case 'D':
317 case 'd':
318 /* Default transformation */
319 return result;
320 case 'V':
321 case 'v':
322 unsigned int count;
323 double view_angle;
325 count = sscanf(line, "V %lf", &view_angle);
327 if (count < 1) {
328 fprintf(stderr, "\n3d-trans-load: Error: "
329 "Malformed 'V' command.\n");
330 exit(1);
333 result.view_angle(view_angle / rtod_multiplier);
335 break;
336 case 'E':
337 case 'e':
338 /* Euclidean transformation data */
339 *is_default = 0;
341 double width, height;
342 double values[6] = {0, 0, -1, 0, 0, 0};
343 int count;
345 count = sscanf(line, "E %lf%lf%lf%lf%lf%lf%lf%lf",
346 &width, &height,
347 &values[1], &values[0], &values[2],
348 &values[4], &values[3], &values[5]);
350 if (count < 8)
351 fprintf(stderr, "\n3d-trans-load: warning: "
352 "Missing args for 'E'\n");
354 if (width != result.scaled_width()
355 || height != result.scaled_height()) {
356 fprintf(stderr, "\n3d-trans-load: Error: "
357 "Scaled image width and/or height mismatch.");
360 for (int i = 3; i < 6; i++) {
361 values [i] /= rtod_multiplier;
364 result.e().set(values);
366 return result;
368 break;
369 default:
370 fprintf(stderr,
371 "\ntrans-load: Error in tload_next: unrecognized command '%s'\n",
372 line);
373 exit(1);
377 return result;
381 * Create a new tsave_t transformation data file structure, used for
382 * writing data to transformation data files.
385 static inline struct tsave_t *tsave_new(const char *filename) {
386 FILE *file = fopen (filename, "w");
387 struct tsave_t *result = NULL;
389 if (!file) {
390 fprintf(stderr, "tsave: Error: could not open transformation data file '%s'.", filename);
391 exit(1);
394 result = (struct tsave_t *)
395 malloc(sizeof(struct tsave_t));
396 result->filename = filename;
397 result->file = file;
398 result->orig = "unknown";
399 result->target = "unknown";
401 fprintf(file, "# created by ALE 3D transformation file handler version %d\n",
402 D3_TFILE_VERSION);
404 fclose(file);
406 return result;
410 * Save the first transformation to a transformation data file associated with
411 * transformation data file structure T, or do nothing if T is NULL. This
412 * function also establishes the output file version.
414 * OFFSET is the transformation to be saved.
416 * IS_PROJECTIVE indicates whether to write a projective transformation.
420 static inline void tsave_first(struct tsave_t *t, pt offset) {
422 if (t == NULL)
423 return;
425 t->file = fopen(t->filename, "a");
427 tfile_output_version = 0;
429 fprintf(t->file, "# producing 3D transformation file syntax version %d\n", tfile_output_version);
430 fprintf(t->file, "W %d\n", tfile_output_version);
432 // fprintf(t->file, "# Comment: Target output file is %s\n", t->target);
433 // fprintf(t->file, "# Comment: Original frame is %s\n", t->orig);
435 const double rtod_multiplier = 180 / M_PI;
437 fprintf(t->file, "V %lf\n", offset.view_angle() * rtod_multiplier);
439 fprintf(t->file, "E ");
440 fprintf(t->file, "%f %f ", (double) offset.scaled_width(), (double) offset.scaled_height());
441 fprintf(t->file, "%f ", (double) offset.e().get_translation(1));
442 fprintf(t->file, "%f ", (double) offset.e().get_translation(0));
443 fprintf(t->file, "%f ", (double) offset.e().get_translation(2));
444 fprintf(t->file, "%f ", (double) offset.e().get_rotation(1) * rtod_multiplier);
445 fprintf(t->file, "%f ", (double) offset.e().get_rotation(0) * rtod_multiplier);
446 fprintf(t->file, "%f ", (double) offset.e().get_rotation(2) * rtod_multiplier);
448 fprintf(t->file, "\n");
450 fclose(t->file);
454 * Save the next transformation to a transformation data file associated with
455 * transformation data file structure T, or do nothing if T is NULL.
457 * OFFSET is the transformation to be saved.
459 * IS_PROJECTIVE indicates whether to write a projective transformation.
463 static inline void tsave_next(struct tsave_t *t, pt offset) {
465 if (t == NULL)
466 return;
468 t->file = fopen(t->filename, "a");
470 const double rtod_multiplier = 180 / M_PI;
472 fprintf(t->file, "V %lf\n", offset.view_angle() * rtod_multiplier);
474 fprintf(t->file, "E ");
475 fprintf(t->file, "%f %f ", (double) offset.scaled_width(), (double) offset.scaled_height());
476 fprintf(t->file, "%f ", (double) offset.e().get_translation(1));
477 fprintf(t->file, "%f ", (double) offset.e().get_translation(0));
478 fprintf(t->file, "%f ", (double) offset.e().get_translation(2));
479 fprintf(t->file, "%f ", (double) offset.e().get_rotation(1) * rtod_multiplier);
480 fprintf(t->file, "%f ", (double) offset.e().get_rotation(0) * rtod_multiplier);
481 fprintf(t->file, "%f ", (double) offset.e().get_rotation(2) * rtod_multiplier);
483 fprintf(t->file, "\n");
485 fclose(t->file);
489 * Write information to a transformation file indicating the target output
490 * file.
493 static inline void tsave_target(struct tsave_t *t, const char *filename) {
494 if (t == NULL)
495 return;
497 t->target = filename;
498 if (t != NULL) {
499 t->file = fopen(t->filename, "a");
502 fclose(t->file);
507 * Write information to a transformation data file indicating the filename
508 * of the original frame (i.e. the first frame in the sequence of input
509 * frames).
512 static inline void tsave_orig(struct tsave_t *t, const char *filename) {
513 if (t == NULL)
514 return;
516 t->orig = filename;
520 * Write information to a transformation data file indicating the filename
521 * of a supplemental frame (i.e. a frame in the sequence of input frames
522 * that is not the first frame).
525 static inline void tsave_info(struct tsave_t *t, const char *filename) {
526 if (t != NULL) {
527 t->file = fopen(t->filename, "a");
529 fprintf(t->file, "# Comment: Supplemental frame %s\n", filename);
531 fclose(t->file);
536 * Write information to a transformation data file indicating the tonal
537 * registration multiplier.
540 static inline void tsave_trm(struct tsave_t *t, ale_real r, ale_real g, ale_real b) {
541 if (t != NULL) {
542 t->file = fopen(t->filename, "a");
544 fprintf(t->file, "# Comment: Exposure [r=%f g=%f b=%f]\n", r, g, b);
546 fclose(t->file);
551 * Write information to a transformation data file indicating the average
552 * pixel magnitude.
555 static inline void tsave_apm(struct tsave_t *t, ale_real r, ale_real g, ale_real b) {
556 if (t != NULL) {
557 t->file = fopen(t->filename, "a");
559 fprintf(t->file, "# Comment: Avg magnitude [r=%f g=%f b=%f]\n", r, g, b);
561 fclose(t->file);
567 * Destroy a tload_t transformation data file structure.
570 static inline void tload_delete(struct tload_t *victim) {
571 if (victim)
572 fclose(victim->file);
573 free(victim);
577 * Destroy a tsave_t transformation data file structure.
580 static inline void tsave_delete(struct tsave_t *victim) {
581 free(victim);
584 #endif