1 /*
2 * coder.c: WFA coder toplevel functions
3 *
4 * Written by: Ullrich Hafner
5 *
6 * This file is part of FIASCO (Fractal Image And Sequence COdec)
7 * Copyright (C) 1994-2000 Ullrich Hafner
8 */
9
10 /*
11 * $Date: 2000/06/14 20:50:51 $
12 * $Author: hafner $
13 * $Revision: 5.1 $
14 * $State: Exp $
15 */
16
17 #define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */
18 #define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */
19 #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */
20
21 #include "config.h"
22 #include "pm_c_util.h"
23 #include "pnm.h"
24
25 #include <math.h>
26 #include <ctype.h>
27
28 #include <string.h>
29
30 #include "nstring.h"
31
32 #include "types.h"
33 #include "macros.h"
34 #include "error.h"
35
36 #include "fiasco.h"
37
38 #include "cwfa.h"
39 #include "misc.h"
40 #include "control.h"
41 #include "bintree.h"
42 #include "subdivide.h"
43 #include "read.h"
44 #include "write.h"
45 #include "image.h"
46 #include "mwfa.h"
47 #include "list.h"
48 #include "decoder.h"
49 #include "motion.h"
50 #include "wfalib.h"
51 #include "domain-pool.h"
52 #include "coeff.h"
53 #include "coder.h"
54 #include "rpf.h"
55
56 /*****************************************************************************
57
58 global variables
59
60 *****************************************************************************/
61
62 const real_t MAXCOSTS = 1e20;
63
64 /*****************************************************************************
65
66 private code
67
68 *****************************************************************************/
69
70 static char *
get_input_image_name(char const * const * templptr,unsigned ith_image)71 get_input_image_name (char const * const *templptr, unsigned ith_image)
72 /*
73 * Construct the i-th image-name using templates.
74 * If the template contains a '[' it must be of the form
75 * "prefix[start-end{+,-}step]suffix"
76 * where "{+,-}step" is optional.
77 * Leading zeros of "start" are significant.
78 *
79 * Example:
80 * "image0[12-01-1].pgm" yields image012.pgm, image011.pgm, ..., image001.pgm
81 *
82 * Return value:
83 * ptr to name of image 'ith_image' or NULL if ith_image is out of range.
84 */
85 {
86 while (*templptr)
87 {
88 const char *template = *templptr++;
89 char *s;
90
91 if (!(s = strchr (template, '['))) /* no template, just a filename */
92 {
93 if (ith_image == 0)
94 return strdup (template);
95 else
96 ith_image--;
97 }
98 else /* template parser */
99 {
100 unsigned n_digits; /* # of digits in image name no. */
101 char *s2;
102 char *suffix; /* characters after template end */
103 char prefix [MAXSTRLEN]; /* chars up to the template start */
104 unsigned first; /* first image number */
105 unsigned last; /* last image number */
106 int image_num; /* current image number */
107 int increment = 1;
108 int dummy;
109
110 strcpy (prefix, template);
111 prefix [s - template] = '\0';
112
113 for (s2 = ++s, n_digits = 0; ISDIGIT (*s2); s2++, n_digits++)
114 ;
115 if (sscanf (s, "%d", &dummy) == 0 || dummy < 0)
116 error ("Input name template conversion failure.\n"
117 "Check spelling of template.");
118 first = (unsigned) dummy;
119
120 if (*s2++ != '-')
121 error ("Input name template conversion failure.\n"
122 "Check spelling of template.");
123
124 for (s = s2; ISDIGIT (*s2); s2++)
125 ;
126 if (sscanf (s, "%d", &dummy) == 0 || dummy < 0)
127 error ("Input name template conversion failure.\n"
128 "Check spelling of template.");
129 last = (unsigned) dummy;
130
131 if (*s2 == '+' || *s2 == '-')
132 {
133 for (s = s2++; ISDIGIT (*s2); s2++)
134 ;
135 if (sscanf (s, "%d", &increment) == 0)
136 error ("Input name template conversion failure.\n"
137 "Check spelling of template.");
138 }
139 if (*s2 != ']')
140 error ("Input name template conversion failure.\n"
141 "Check spelling of template.");
142 suffix = s2 + 1;
143
144 image_num = first + increment * ith_image;
145 if (image_num < 0)
146 error ("Input name template conversion failure.\n"
147 "Check spelling of template.");
148
149 if ((increment > 0 && (unsigned) image_num > last) ||
150 (increment <= 0 && (unsigned) image_num < last))
151 {
152 /* TODO: check this */
153 ith_image -= (last - first) / increment + 1;
154 }
155 else
156 {
157 char formatstr [MAXSTRLEN];
158 /* format string for image filename */
159 char image_name [MAXSTRLEN];
160 /* image file name to be composed */
161
162 strcpy (formatstr, "%s%0?d%s");
163 formatstr [4] = '0' + (char) n_digits;
164 sprintf (image_name, formatstr, prefix, image_num, suffix);
165 return strdup (image_name);
166 }
167 }
168 }
169 return NULL;
170 }
171
172
173
174 static coding_t *
alloc_coder(char const * const * const inputname,const c_options_t * const options,wfa_info_t * const wi,unsigned int const stdinwidth,unsigned int const stdinheight,xelval const stdinmaxval,int const stdinformat)175 alloc_coder (char const * const * const inputname,
176 const c_options_t * const options,
177 wfa_info_t * const wi,
178 unsigned int const stdinwidth,
179 unsigned int const stdinheight,
180 xelval const stdinmaxval,
181 int const stdinformat)
182 /*
183 * Coder structure constructor.
184 * Allocate memory for the FIASCO coder structure and
185 * fill in default values specified by 'options'.
186 *
187 * Return value:
188 * pointer to the new coder structure or NULL on error
189 */
190 {
191 coding_t * c;
192
193 c = NULL; /* initial value */
194
195 /*
196 * Check whether all specified image frames are readable and of same type
197 */
198 {
199 char *filename;
200 int width, w = 0, height, h = 0;
201 bool_t color, c = NO;
202 unsigned n;
203
204 for (n = 0; (filename = get_input_image_name (inputname, n)); n++)
205 {
206 xelval maxval;
207 int format;
208 if (streq(filename, "-")) {
209 width = stdinwidth;
210 height = stdinheight;
211 maxval = stdinmaxval;
212 format = stdinformat;
213 } else {
214 FILE *file;
215
216 file = pm_openr(filename);
217
218 pnm_readpnminit(file, &width, &height, &maxval, &format);
219
220 pm_close(file);
221 }
222 color = (PNM_FORMAT_TYPE(format) == PPM_FORMAT) ? TRUE: FALSE;
223
224 if (n > 0)
225 {
226 if (w != width || h != height || c != color)
227 {
228 set_error (_("Format of image frame `%s' doesn't match."),
229 filename ? filename : "<stdin>");
230 return NULL;
231 }
232 }
233 else
234 {
235 w = width;
236 h = height;
237 c = color;
238 }
239 Free (filename);
240 }
241 wi->frames = n;
242 wi->width = w;
243 wi->height = h;
244 wi->color = c;
245 }
246
247 /*
248 * Levels ...
249 */
250 {
251 unsigned lx, ly;
252
253 lx = (unsigned) (log2 (wi->width - 1) + 1);
254 ly = (unsigned) (log2 (wi->height - 1) + 1);
255
256 wi->level = MAX(lx, ly) * 2 - ((ly == lx + 1) ? 1 : 0);
257 }
258
259 c = Calloc (1, sizeof (coding_t));
260
261 c->options = *options;
262 c->options.lc_min_level = MAX(options->lc_min_level, 3);
263 c->options.lc_max_level = MIN(options->lc_max_level, wi->level - 1);
264
265 c->tiling = alloc_tiling (options->tiling_method,
266 options->tiling_exponent, wi->level);
267
268 if (wi->frames > 1 && c->tiling->exponent > 0)
269 {
270 c->tiling->exponent = 0;
271 warning (_("Image tiling valid only with still image compression."));
272 }
273
274 if (c->options.lc_max_level >= wi->level - c->tiling->exponent)
275 {
276 message ("'max_level' changed from %d to %d "
277 "because of image tiling level.",
278 c->options.lc_max_level, wi->level - c->tiling->exponent - 1);
279 c->options.lc_max_level = wi->level - c->tiling->exponent - 1;
280 }
281
282 if (c->options.lc_min_level > c->options.lc_max_level)
283 c->options.lc_min_level = c->options.lc_max_level;
284
285 /*
286 * p_min_level, p_max_level min and max level for ND/MC prediction
287 * [p_min_level, p_max_level] must be a subset of [min_level, max_level] !
288 */
289 wi->p_min_level = MAX(options->p_min_level, c->options.lc_min_level);
290 wi->p_max_level = MIN(options->p_max_level, c->options.lc_max_level);
291 if (wi->p_min_level > wi->p_max_level)
292 wi->p_min_level = wi->p_max_level;
293
294 c->options.images_level = MIN(c->options.images_level,
295 c->options.lc_max_level - 1);
296
297 c->products_level = MAX(0, ((signed int) c->options.lc_max_level
298 - (signed int) c->options.images_level - 1));
299 c->pixels = Calloc (size_of_level (c->options.lc_max_level),
300 sizeof (real_t));
301 c->images_of_state = Calloc (MAXSTATES, sizeof (real_t *));
302 c->ip_images_state = Calloc (MAXSTATES, sizeof (real_t *));
303 c->ip_states_state = Calloc (MAXSTATES * MAXLEVEL, sizeof (real_t *));
304
305 debug_message ("Imageslevel :%d, Productslevel :%d",
306 c->options.images_level, c->products_level);
307 debug_message ("Memory : (%d + %d + %d * 'states') * 'states' + %d",
308 size_of_tree (c->options.images_level) * 4,
309 size_of_tree (c->products_level) * 4,
310 (c->options.lc_max_level - c->options.images_level),
311 size_of_level (c->options.lc_max_level));
312
313 /*
314 * Domain pools ...
315 */
316 c->domain_pool = NULL;
317 c->d_domain_pool = NULL;
318
319 /*
320 * Coefficients model ...
321 */
322 c->coeff = NULL;
323 c->d_coeff = NULL;
324
325 /*
326 * Max. number of states and edges
327 */
328 wi->max_states = MAX(MIN(options->max_states, MAXSTATES), 1);
329 c->options.max_elements = MAX(MIN(options->max_elements, MAXEDGES), 1);
330
331 /*
332 * Title and comment strings
333 */
334 wi->title = strdup (options->title);
335 wi->comment = strdup (options->comment);
336
337 /*
338 * Reduced precision format
339 */
340 wi->rpf
341 = alloc_rpf (options->rpf_mantissa, options->rpf_range);
342 wi->dc_rpf
343 = alloc_rpf (options->dc_rpf_mantissa, options->dc_rpf_range);
344 wi->d_rpf
345 = alloc_rpf (options->d_rpf_mantissa, options->d_rpf_range);
346 wi->d_dc_rpf
347 = alloc_rpf (options->d_dc_rpf_mantissa, options->d_dc_rpf_range);
348
349 /*
350 * Color image options ...
351 */
352 wi->chroma_max_states = MAX(1, options->chroma_max_states);
353
354 /*
355 * Set up motion compensation struct.
356 * p_min_level, p_max_level are also used for ND prediction
357 */
358 wi->search_range = options->search_range;
359 wi->fps = options->fps;
360 wi->half_pixel = options->half_pixel_prediction;
361 wi->cross_B_search = options->half_pixel_prediction;
362 wi->B_as_past_ref = options->B_as_past_ref;
363 wi->smoothing = options->smoothing;
364
365 c->mt = alloc_motion (wi);
366
367 return c;
368 }
369
370
371
372 static void
free_coder(coding_t * c)373 free_coder (coding_t *c)
374 /*
375 * Coder struct destructor:
376 * Free memory of 'coder' struct.
377 *
378 * No return value.
379 *
380 * Side effects:
381 * structure 'coder' is discarded.
382 */
383 {
384 free_tiling (c->tiling);
385 free_motion (c->mt);
386
387 Free (c->pixels);
388 Free (c->images_of_state);
389 Free (c->ip_images_state);
390 Free (c->ip_states_state);
391 Free (c);
392 }
393
394
395
396
397 static frame_type_e
pattern2type(unsigned frame,const char * pattern)398 pattern2type (unsigned frame, const char *pattern)
399 {
400 int tmp = TOUPPER (pattern [frame % strlen (pattern)]);
401 frame_type_e retval;
402
403 switch (tmp)
404 {
405 case 'I':
406 retval = I_FRAME;
407 break;
408 case 'B':
409 retval = B_FRAME;
410 break;
411 case 'P':
412 retval = P_FRAME;
413 break;
414 default:
415 error ("Frame type %c not valid. Choose one of I,B or P.", tmp);
416 }
417 return retval;
418 }
419
420
421
422 static void
print_statistics(char c,real_t costs,const wfa_t * wfa,const image_t * image,const range_t * range)423 print_statistics (char c, real_t costs, const wfa_t *wfa, const image_t *image,
424 const range_t *range)
425 {
426 unsigned max_level, min_level, state, label, lincomb;
427
428 for (max_level = 0, min_level = MAXLEVEL, state = wfa->basis_states;
429 state < wfa->states; state++)
430 {
431 for (lincomb = 0, label = 0; label < MAXLABELS; label++)
432 lincomb += isrange(wfa->tree[state][label]) ? 1 : 0;
433
434 if (lincomb)
435 {
436 max_level = MAX(max_level,
437 (unsigned) (wfa->level_of_state [state] - 1));
438 min_level = MIN(min_level,
439 (unsigned) (wfa->level_of_state [state] - 1));
440 }
441 }
442 debug_message ("Image partitioning: maximum level %d , minimum level %d",
443 max_level, min_level);
444 debug_message ("WFA contains %d states (%d basis states).",
445 wfa->states, wfa->basis_states);
446 debug_message ("Estimated error: %.2f (RMSE: %.2f, PSNR: %.2f dB).",
447 (double) range->err,
448 sqrt (range->err / image->width / image->height),
449 10 * log ( 255.0 * 255.0 /
450 (range->err / image->width / image->height))
451 / log (10.0));
452 debug_message ("Estimated filesize: %.0f bits (%.0f bytes).",
453 (double) (range->tree_bits + range->matrix_bits
454 + range->weights_bits
455 + range->mv_tree_bits + range->mv_coord_bits
456 + range->nd_tree_bits + range->nd_weights_bits),
457 (double) (range->tree_bits + range->matrix_bits
458 + range->weights_bits + range->mv_tree_bits
459 + range->mv_coord_bits + range->nd_tree_bits
460 + range->nd_weights_bits) / 8);
461 if (c)
462 debug_message ("(%cT: %.0f, %cM: %.0f, %cW: %.0f, %cMC: %.0f, "
463 "%cMV: %.0f, %cNT: %.0f, %cNW: %.0f.)",
464 c, (double) range->tree_bits,
465 c, (double) range->matrix_bits,
466 c, (double) range->weights_bits,
467 c, (double) range->mv_tree_bits,
468 c, (double) range->mv_coord_bits,
469 c, (double) range->nd_tree_bits,
470 c, (double) range->nd_weights_bits);
471 else
472 debug_message ("(T: %.0f, M: %.0f, W: %.0f, MC: %.0f, MV: %.0f, "
473 "NT: %.0f, NW: %.0f.)",
474 (double) range->tree_bits,
475 (double) range->matrix_bits,
476 (double) range->weights_bits,
477 (double) range->mv_tree_bits,
478 (double) range->mv_coord_bits,
479 (double) range->nd_tree_bits,
480 (double) range->nd_weights_bits);
481 debug_message ("Total costs : %.2f", (double) costs);
482 }
483
484
485
486 static void
frame_coder(wfa_t * wfa,coding_t * c,bitfile_t * output)487 frame_coder (wfa_t *wfa, coding_t *c, bitfile_t *output)
488 /*
489 *
490 * WFA Coding of next frame. All important coding parameters are
491 * stored in 'c'. The generated 'wfa' is written to stream 'output'
492 * immediately after coding.
493 *
494 * No return value.
495 */
496 {
497 unsigned state;
498 range_t range; /* first range == the entire image */
499 real_t costs; /* total costs (minimized quantity) */
500 unsigned bits; /* number of bits written on disk */
501 clock_t ptimer;
502
503 prg_timer (&ptimer, START);
504
505 bits = bits_processed (output);
506
507 init_tree_model (&c->tree);
508 init_tree_model (&c->p_tree);
509
510 c->domain_pool
511 = alloc_domain_pool (c->options.id_domain_pool,
512 wfa->wfainfo->max_states,
513 c->options.max_elements, wfa);
514 c->d_domain_pool
515 = alloc_domain_pool ((c->options.prediction
516 || c->mt->frame_type != I_FRAME)
517 ? c->options.id_d_domain_pool : "constant",
518 wfa->wfainfo->max_states,
519 c->options.max_elements, wfa);
520
521 c->coeff = alloc_coeff_model (c->options.id_rpf_model,
522 wfa->wfainfo->rpf,
523 wfa->wfainfo->dc_rpf,
524 c->options.lc_min_level,
525 c->options.lc_max_level);
526 c->d_coeff = alloc_coeff_model (c->options.id_d_rpf_model,
527 wfa->wfainfo->d_rpf,
528 wfa->wfainfo->d_dc_rpf,
529 c->options.lc_min_level,
530 c->options.lc_max_level);
531
532 if (!c->mt->original->color) /* grayscale image */
533 {
534 memset (&range, 0, sizeof (range_t));
535 range.level = wfa->wfainfo->level;
536
537 costs = subdivide (MAXCOSTS, GRAY, RANGE, &range, wfa, c,
538 c->options.prediction || c->mt->frame_type != I_FRAME,
539 NO);
540 if (c->options.progress_meter != FIASCO_PROGRESS_NONE)
541 message ("");
542
543 if (isrange (range.tree)) /* entire image is approx. by lc? */
544 error ("No root state generated!");
545 else
546 wfa->root_state = range.tree;
547
548 print_statistics ('\0', costs, wfa, c->mt->original, &range);
549 }
550 else
551 {
552 int YCb_node = -1;
553 int tree [3]; /* 3 root states of each color comp. */
554 color_e band;
555
556 /*
557 * When compressing color images, the three color components (YCbCr)
558 * are copied into a large image:
559 * [ Y Cr ]
560 * [ Cb 0 ]
561 * I.e. the color components of an image are processed in a row.
562 * After all components are compressed, virtual states are generated
563 * to describe the large image.
564 */
565 for (band = first_band (YES); band <= last_band (YES) ; band++)
566 {
567 debug_message ("Encoding color component %d", band);
568 tree [band] = RANGE;
569 if (band == Cb)
570 {
571 unsigned min_level;
572
573 c->domain_pool->chroma (wfa->wfainfo->chroma_max_states, wfa,
574 c->domain_pool->model);
575 /*
576 * Don't use a finer partitioning for the chrominancy bands
577 * than for the luminancy band.
578 */
579 for (min_level = MAXLEVEL, state = wfa->basis_states;
580 state < wfa->states; state++)
581 {
582 unsigned lincomb, label;
583
584 for (lincomb = 0, label = 0; label < MAXLABELS; label++)
585 lincomb += isrange (wfa->tree [state][label]) ? 1 : 0;
586 if (lincomb)
587 min_level = MIN(min_level,
588 (unsigned) (wfa->level_of_state [state]
589 - 1));
590 }
591 c->options.lc_min_level = min_level;
592 if (c->mt->frame_type != I_FRAME) /* subtract mc of luminance */
593 subtract_mc (c->mt->original, c->mt->past, c->mt->future,
594 wfa);
595 }
596
597 memset (&range, 0, sizeof (range_t));
598 range.level = wfa->wfainfo->level;
599
600 costs = subdivide (MAXCOSTS, band, tree [Y], &range, wfa, c,
601 c->mt->frame_type != I_FRAME && band == Y, NO);
602 if (c->options.progress_meter != FIASCO_PROGRESS_NONE)
603 message ("");
604 {
605 char colors [] = {'Y', 'B', 'R'};
606
607 print_statistics (colors [band], costs, wfa,
608 c->mt->original, &range);
609 }
610
611 if (isrange (range.tree)) /* whole image is approx. by a l.c. */
612 error ("No root state generated for color component %d!", band);
613 else
614 tree[band] = range.tree;
615
616 if (band == Cb)
617 {
618 wfa->tree [wfa->states][0] = tree[Y];
619 wfa->tree [wfa->states][1] = tree[Cb];
620 YCb_node = wfa->states;
621 append_state (YES, compute_final_distribution(wfa->states, wfa),
622 wfa->wfainfo->level + 1, wfa, c);
623 }
624 }
625 /*
626 * generate two virtual states (*)
627 *
628 * *
629 * / \
630 * + *
631 * / \ /
632 * Y CbCr
633 */
634 wfa->tree [wfa->states][0] = tree[Cr];
635 wfa->tree [wfa->states][1] = RANGE;
636 append_state (YES, compute_final_distribution (wfa->states, wfa),
637 wfa->wfainfo->level + 1, wfa, c);
638 wfa->tree[wfa->states][0] = YCb_node;
639 wfa->tree[wfa->states][1] = wfa->states - 1;
640 append_state (YES, compute_final_distribution (wfa->states, wfa),
641 wfa->wfainfo->level + 2, wfa, c);
642
643 wfa->root_state = wfa->states - 1;
644 }
645
646 for (state = wfa->basis_states; state < MAXSTATES; state++)
647 {
648 unsigned level;
649
650 if (c->images_of_state [state])
651 {
652 Free (c->images_of_state [state]);
653 c->images_of_state [state] = NULL;
654 }
655 if (c->ip_images_state [state])
656 {
657 Free (c->ip_images_state [state]);
658 c->ip_images_state [state] = NULL;
659 }
660 for (level = c->options.images_level + 1;
661 level <= c->options.lc_max_level;
662 level++)
663 if (c->ip_states_state [state][level])
664 {
665 Free (c->ip_states_state [state][level]);
666 c->ip_states_state [state][level] = NULL;
667 }
668
669 }
670
671 locate_delta_images (wfa);
672 write_next_wfa (wfa, c, output);
673
674 bits = bits_processed (output) - bits;
675 debug_message ("Total number of bits written: %d (%d bytes, %5.3f bpp)",
676 bits, bits >> 3,
677 bits / (double) (c->mt->original->height
678 * c->mt->original->width));
679 debug_message ("Total encoding time (real): %d sec",
680 prg_timer (&ptimer, STOP) / 1000);
681
682 c->domain_pool->free (c->domain_pool);
683 c->d_domain_pool->free (c->d_domain_pool);
684
685 c->coeff->free (c->coeff);
686 c->d_coeff->free (c->d_coeff);
687 }
688
689
690
691 static void
video_coder(char const * const * const image_template,bitfile_t * const output,wfa_t * const wfa,coding_t * const c,unsigned int const stdinwidth,unsigned int const stdinheight,unsigned int const stdinmaxval,unsigned int const stdinformat)692 video_coder(char const * const * const image_template,
693 bitfile_t * const output,
694 wfa_t * const wfa,
695 coding_t * const c,
696 unsigned int const stdinwidth,
697 unsigned int const stdinheight,
698 unsigned int const stdinmaxval,
699 unsigned int const stdinformat)
700 /*
701 * Toplevel function to encode a sequence of video frames specified
702 * by 'image_template'. The output is written to stream 'output'.
703 * Coding options are given by 'c'.
704 *
705 * No return value.
706 */
707 {
708 unsigned display; /* picture number in display order */
709 int future_display; /* number of future reference */
710 int frame; /* current frame number */
711 char *image_name;
712 /* image name of current frame. File name or "-" for Standard Input */
713 image_t *reconst = NULL; /* decoded reference image */
714 bool_t future_frame = NO; /* YES if last frame was in future */
715
716 debug_message ("Generating %d WFA's ...", wfa->wfainfo->frames);
717
718 future_display = -1;
719 frame = -1;
720 display = 0;
721
722 while ((image_name = get_input_image_name (image_template, display)))
723 {
724 frame_type_e type; /* current frame type: I, B, P */
725
726 /*
727 * Determine type of next frame.
728 * Skip already coded frames (future reference!)
729 */
730 if (display == 0 && !c->options.reference_filename)
731 type = I_FRAME; /* Force first frame to be intra */
732 else
733 type = pattern2type (display, c->options.pattern);
734
735 if (type != I_FRAME && c->options.reference_filename)
736 /* Load reference from disk */
737 {
738 debug_message ("Reading reference frame `%s'.",
739 c->options.reference_filename);
740 reconst = read_image_file (c->options.reference_filename);
741 c->options.reference_filename = NULL;
742 }
743 if ((int) display == future_display)
744 {
745 /* Skip already coded future ref */
746 display++;
747 continue;
748 }
749 else if (type == B_FRAME && (int) display > future_display)
750 {
751 unsigned i = display;
752 /*
753 * Search for future reference
754 */
755 while (type == B_FRAME)
756 {
757 char *name; /* image name of future frame */
758
759 i++;
760 name = get_input_image_name (image_template, i);
761
762 if (!name) /* Force last valid frame to be 'P' */
763 {
764 future_display = i - 1;
765 type = P_FRAME;
766 }
767 else
768 {
769 future_display = i;
770 image_name = name;
771 type = pattern2type (i, c->options.pattern);
772 }
773 frame = future_display;
774 }
775 }
776 else
777 {
778 frame = display;
779 display++;
780 }
781
782 debug_message ("Coding \'%s\' [%c-frame].", image_name,
783 type == I_FRAME ? 'I' : (type == P_FRAME ? 'P' : 'B'));
784
785 /*
786 * Depending on current frame type update past and future frames
787 * which are needed as reference frames.
788 */
789 c->mt->frame_type = type;
790 if (type == I_FRAME)
791 {
792 if (c->mt->past) /* discard past frame */
793 free_image (c->mt->past);
794 c->mt->past = NULL;
795 if (c->mt->future) /* discard future frame */
796 free_image (c->mt->future);
797 c->mt->future = NULL;
798 if (reconst) /* discard current frame */
799 free_image (reconst);
800 reconst = NULL;
801 }
802 else if (type == P_FRAME)
803 {
804 if (c->mt->past) /* discard past frame */
805 free_image (c->mt->past);
806 c->mt->past = reconst; /* past frame <- current frame */
807 reconst = NULL;
808 if (c->mt->future) /* discard future frame */
809 free_image (c->mt->future);
810 c->mt->future = NULL;
811 }
812 else /* B_FRAME */
813 {
814 if (future_frame) /* last frame was future frame */
815 {
816 if (c->mt->future) /* discard future frame */
817 free_image (c->mt->future);
818 c->mt->future = reconst; /* future frame <- current frame */
819 reconst = NULL;
820 }
821 else
822 {
823 if (wfa->wfainfo->B_as_past_ref == YES)
824 {
825 if (c->mt->past) /* discard past frame */
826 free_image (c->mt->past);
827 c->mt->past = reconst; /* past frame <- current frame */
828 reconst = NULL;
829 }
830 else
831 {
832 if (reconst) /* discard current frame */
833 free_image (reconst);
834 reconst = NULL;
835 }
836 }
837 }
838
839 /*
840 * Start WFA coding of current frame
841 */
842 future_frame = frame == future_display;
843 c->mt->number = frame;
844
845 if (streq(image_name, "-"))
846 c->mt->original = read_image_stream(stdin,
847 stdinwidth, stdinheight,
848 stdinmaxval, stdinformat);
849 else
850 c->mt->original = read_image_file(image_name);
851
852 if (c->tiling->exponent && type == I_FRAME)
853 perform_tiling (c->mt->original, c->tiling);
854
855 frame_coder (wfa, c, output);
856
857 /*
858 * Regenerate image:
859 * 1. Compute approximation of WFA ranges (real image bintree order)
860 * 2. Generate byte image in rasterscan order
861 * 3. Apply motion compensation
862 */
863 reconst = decode_image (wfa->wfainfo->width, wfa->wfainfo->height,
864 FORMAT_4_4_4, NULL, wfa);
865
866 if (type != I_FRAME)
867 restore_mc (0, reconst, c->mt->past, c->mt->future, wfa);
868
869 if (c->mt->original)
870 free_image (c->mt->original);
871 c->mt->original = NULL;
872
873 remove_states (wfa->basis_states, wfa); /* Clear WFA structure */
874 }
875
876 if (reconst)
877 free_image (reconst);
878 if (c->mt->future)
879 free_image (c->mt->future);
880 if (c->mt->past)
881 free_image (c->mt->past);
882 if (c->mt->original)
883 free_image (c->mt->original);
884 }
885
886
887
888 static void
read_stdin_header(const char * const * const template,unsigned int * const widthP,unsigned int * const heightP,xelval * const maxvalP,int * const formatP)889 read_stdin_header(const char * const * const template,
890 unsigned int * const widthP,
891 unsigned int * const heightP,
892 xelval * const maxvalP,
893 int * const formatP)
894 /* Read the PNM header from the Standard Input stream, if 'template' says
895 one of the images is to come from Standard Input.
896
897 Return the contents of that stream as *widthP, etc.
898 */
899 {
900 unsigned int i;
901 bool endOfList;
902 bool stdinFound;
903
904 for (i = 0, stdinFound = FALSE, endOfList = FALSE; !endOfList; ++i) {
905 const char * const name = get_input_image_name(template, i);
906
907 if (!name)
908 endOfList = TRUE;
909 else {
910 if (streq(name, "-"))
911 stdinFound = TRUE;
912 }
913 }
914
915 if (stdinFound) {
916 int width, height;
917
918 pnm_readpnminit(stdin, &width, &height, maxvalP, formatP);
919
920 *widthP = width;
921 *heightP = height;
922 }
923 }
924
925
926
927 /*****************************************************************************
928
929 public code
930
931 *****************************************************************************/
932
933 int
fiasco_coder(char const * const * inputname,const char * outputname,float quality,const fiasco_c_options_t * options)934 fiasco_coder (char const * const *inputname, const char *outputname,
935 float quality, const fiasco_c_options_t *options)
936 /*
937 * FIASCO coder.
938 * Encode image or video frames given by the array of filenames `inputname'
939 * and write to the outputfile `outputname'.
940 * If 'inputname' = NULL or
941 * 'inputname [0]' == NULL or
942 * 'inputname [0]' == "-", read standard input.
943 * If 'outputname' == NULL or "-", write on standard output.
944 * 'quality' defines the approximation quality and is 1 (worst) to 100 (best).
945 *
946 * Return value:
947 * 1 on success
948 * 0 otherwise
949 */
950 {
951 try
952 {
953 char const * const default_input [] = {"-", NULL};
954 fiasco_c_options_t *default_options = NULL;
955 const c_options_t *cop;
956 char const * const *template;
957 unsigned int stdinheight, stdinwidth;
958 xelval stdinmaxval;
959 int stdinformat;
960
961 /*
962 * Check parameters
963 */
964 if (!inputname || !inputname [0] || streq (inputname [0], "-"))
965 template = default_input;
966 else
967 template = inputname;
968
969 if (quality <= 0)
970 {
971 set_error (_("Compression quality has to be positive."));
972 return 0;
973 }
974 else if (quality >= 100)
975 {
976 warning (_("Quality typically is 1 (worst) to 100 (best).\n"
977 "Be prepared for a long running time."));
978 }
979
980 if (options)
981 {
982 cop = cast_c_options ((fiasco_c_options_t *) options);
983 if (!cop)
984 return 0;
985 }
986 else
987 {
988 default_options = fiasco_c_options_new ();
989 cop = cast_c_options (default_options);
990 }
991
992 read_stdin_header(template, &stdinwidth, &stdinheight,
993 &stdinmaxval, &stdinformat);
994
995 /*
996 * Open output stream and initialize WFA
997 */
998 {
999 bitfile_t *output = open_bitfile (outputname, "FIASCO_DATA",
1000 WRITE_ACCESS);
1001 if (!output)
1002 {
1003 set_error (_("Can't write outputfile `%s'.\n%s"),
1004 outputname ? outputname : "<stdout>",
1005 get_system_error ());
1006 if (default_options)
1007 fiasco_c_options_delete (default_options);
1008 return 0;
1009 }
1010 else
1011 {
1012 wfa_t *wfa = alloc_wfa (YES);
1013 coding_t *c = alloc_coder(template, cop, wfa->wfainfo,
1014 stdinwidth, stdinheight,
1015 stdinmaxval, stdinformat);
1016
1017 read_basis (cop->basis_name, wfa);
1018 append_basis_states (wfa->basis_states, wfa, c);
1019
1020 c->price = 128 * 64 / quality;
1021
1022 video_coder (template, output, wfa, c,
1023 stdinwidth, stdinheight, stdinmaxval,
1024 stdinformat);
1025
1026 close_bitfile (output);
1027 free_wfa (wfa);
1028 free_coder (c);
1029
1030 if (default_options)
1031 fiasco_c_options_delete (default_options);
1032 }
1033 }
1034 return 1;
1035 }
1036 catch
1037 {
1038 return 0;
1039 }
1040 }
1041
1042