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