diff options
Diffstat (limited to 'converter/other/fiasco/codec')
-rw-r--r-- | converter/other/fiasco/codec/coder.c | 1472 | ||||
-rw-r--r-- | converter/other/fiasco/codec/decoder.c | 1801 | ||||
-rw-r--r-- | converter/other/fiasco/codec/dfiasco.c | 2 | ||||
-rw-r--r-- | converter/other/fiasco/codec/options.c | 2 |
4 files changed, 1678 insertions, 1599 deletions
diff --git a/converter/other/fiasco/codec/coder.c b/converter/other/fiasco/codec/coder.c index df878d87..927ebbda 100644 --- a/converter/other/fiasco/codec/coder.c +++ b/converter/other/fiasco/codec/coder.c @@ -1,8 +1,8 @@ /* - * coder.c: WFA coder toplevel functions + * coder.c: WFA coder toplevel functions * - * Written by: Ullrich Hafner - * + * Written by: Ullrich Hafner + * * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> */ @@ -18,6 +18,7 @@ #define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ #include "config.h" +#include "pm_c_util.h" #include "pnm.h" #include <math.h> @@ -53,328 +54,320 @@ /***************************************************************************** - global variables + global variables *****************************************************************************/ -const real_t MAXCOSTS = 1e20; +const real_t MAXCOSTS = 1e20; /***************************************************************************** - prototypes + private code *****************************************************************************/ -static coding_t * -alloc_coder (char const * const *inputname, const c_options_t *options, - wfa_info_t *wi); -static void -free_coder (coding_t *c); static char * -get_input_image_name (char const * const *templptr, unsigned ith_image); -static void -video_coder (char const * const *image_template, bitfile_t *output, - wfa_t *wfa, coding_t *c); -static void -frame_coder (wfa_t *wfa, coding_t *c, bitfile_t *output); -static void -print_statistics (char c, real_t costs, const wfa_t *wfa, const image_t *image, - const range_t *range); -static frame_type_e -pattern2type (unsigned frame, const char *pattern); - -/***************************************************************************** - - public code - -*****************************************************************************/ - -int -fiasco_coder (char const * const *inputname, const char *outputname, - float quality, const fiasco_c_options_t *options) +get_input_image_name (char const * const *templptr, unsigned ith_image) /* - * FIASCO coder. - * Encode image or video frames given by the array of filenames `inputname' - * and write to the outputfile `outputname'. - * If 'inputname' = NULL or - * 'inputname [0]' == NULL or - * 'inputname [0]' == "-", read standard input. - * If 'outputname' == NULL or "-", write on standard output. - * 'quality' defines the approximation quality and is 1 (worst) to 100 (best). + * Construct the i-th image-name using templates. + * If the template contains a '[' it must be of the form + * "prefix[start-end{+,-}step]suffix" + * where "{+,-}step" is optional. + * Leading zeros of "start" are significant. + * + * Example: + * "image0[12-01-1].pgm" yields image012.pgm, image011.pgm, ..., image001.pgm * * Return value: - * 1 on success - * 0 otherwise + * ptr to name of image 'ith_image' or NULL if ith_image is out of range. */ { - try - { - char const * const default_input [] = {"-", NULL}; - fiasco_c_options_t *default_options = NULL; - const c_options_t *cop; - char const * const *template; - - /* - * Check parameters - */ - if (!inputname || !inputname [0] || streq (inputname [0], "-")) - template = default_input; - else - template = inputname; - - if (quality <= 0) - { - set_error (_("Compression quality has to be positive.")); - return 0; - } - else if (quality >= 100) - { - warning (_("Quality typically is 1 (worst) to 100 (best).\n" - "Be prepared for a long running time.")); - } - - if (options) - { - cop = cast_c_options ((fiasco_c_options_t *) options); - if (!cop) - return 0; - } - else - { - default_options = fiasco_c_options_new (); - cop = cast_c_options (default_options); - } - - /* - * Open output stream and initialize WFA - */ - { - bitfile_t *output = open_bitfile (outputname, "FIASCO_DATA", - WRITE_ACCESS); - if (!output) - { - set_error (_("Can't write outputfile `%s'.\n%s"), - outputname ? outputname : "<stdout>", - get_system_error ()); - if (default_options) - fiasco_c_options_delete (default_options); - return 0; - } - else - { - wfa_t *wfa = alloc_wfa (YES); - coding_t *c = alloc_coder (template, cop, wfa->wfainfo); - - read_basis (cop->basis_name, wfa); - append_basis_states (wfa->basis_states, wfa, c); - - c->price = 128 * 64 / quality; - - video_coder (template, output, wfa, c); - - close_bitfile (output); - free_wfa (wfa); - free_coder (c); - - if (default_options) - fiasco_c_options_delete (default_options); - } - } - return 1; - } - catch - { - return 0; - } -} + while (*templptr) + { + const char *template = *templptr++; + char *s; + + if (!(s = strchr (template, '['))) /* no template, just a filename */ + { + if (ith_image == 0) + return strdup (template); + else + ith_image--; + } + else /* template parser */ + { + unsigned n_digits; /* # of digits in image name no. */ + char *s2; + char *suffix; /* characters after template end */ + char prefix [MAXSTRLEN]; /* chars up to the template start */ + unsigned first; /* first image number */ + unsigned last; /* last image number */ + int image_num; /* current image number */ + int increment = 1; + int dummy; + + strcpy (prefix, template); + prefix [s - template] = '\0'; + + for (s2 = ++s, n_digits = 0; ISDIGIT (*s2); s2++, n_digits++) + ; + if (sscanf (s, "%d", &dummy) == 0 || dummy < 0) + error ("Input name template conversion failure.\n" + "Check spelling of template."); + first = (unsigned) dummy; + + if (*s2++ != '-') + error ("Input name template conversion failure.\n" + "Check spelling of template."); + + for (s = s2; ISDIGIT (*s2); s2++) + ; + if (sscanf (s, "%d", &dummy) == 0 || dummy < 0) + error ("Input name template conversion failure.\n" + "Check spelling of template."); + last = (unsigned) dummy; + + if (*s2 == '+' || *s2 == '-') + { + for (s = s2++; ISDIGIT (*s2); s2++) + ; + if (sscanf (s, "%d", &increment) == 0) + error ("Input name template conversion failure.\n" + "Check spelling of template."); + } + if (*s2 != ']') + error ("Input name template conversion failure.\n" + "Check spelling of template."); + suffix = s2 + 1; + + image_num = first + increment * ith_image; + if (image_num < 0) + error ("Input name template conversion failure.\n" + "Check spelling of template."); + + if ((increment > 0 && (unsigned) image_num > last) || + (increment <= 0 && (unsigned) image_num < last)) + { + /* TODO: check this */ + ith_image -= (last - first) / increment + 1; + } + else + { + char formatstr [MAXSTRLEN]; + /* format string for image filename */ + char image_name [MAXSTRLEN]; + /* image file name to be composed */ + + strcpy (formatstr, "%s%0?d%s"); + formatstr [4] = '0' + (char) n_digits; + sprintf (image_name, formatstr, prefix, image_num, suffix); + return strdup (image_name); + } + } + } + return NULL; +} -/***************************************************************************** - private code - -*****************************************************************************/ static coding_t * -alloc_coder (char const * const *inputname, const c_options_t *options, - wfa_info_t *wi) +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) /* * Coder structure constructor. * Allocate memory for the FIASCO coder structure and * fill in default values specified by 'options'. * * Return value: - * pointer to the new coder structure or NULL on error + * pointer to the new coder structure or NULL on error */ { - coding_t *c = NULL; + coding_t * c; + + c = NULL; /* initial value */ /* * Check whether all specified image frames are readable and of same type */ - { - char *filename; - int width, w = 0, height, h = 0; - bool_t color, c = NO; - unsigned n; + { + char *filename; + int width, w = 0, height, h = 0; + bool_t color, c = NO; + unsigned n; - for (n = 0; (filename = get_input_image_name (inputname, n)); n++) - { - FILE *file; - xelval maxval; - int format; - if (filename == NULL) - file = stdin; - else - file = pm_openr(filename); - pnm_readpnminit(file, &width, &height, &maxval, &format); - color = (PNM_FORMAT_TYPE(format) == PPM_FORMAT) ? TRUE: FALSE; - - pm_close(file); - if (n) - { - if (w != width || h != height || c != color) - { - set_error (_("Format of image frame `%s' doesn't match."), - filename ? filename : "<stdin>"); - return NULL; - } - } - else - { - w = width; - h = height; - c = color; - } - Free (filename); - } - wi->frames = n; - wi->width = w; - wi->height = h; - wi->color = c; - } + for (n = 0; (filename = get_input_image_name (inputname, n)); n++) + { + xelval maxval; + int format; + if (streq(filename, "-")) { + width = stdinwidth; + height = stdinheight; + maxval = stdinmaxval; + format = stdinformat; + } else { + FILE *file; + + file = pm_openr(filename); + + pnm_readpnminit(file, &width, &height, &maxval, &format); + + pm_close(file); + } + color = (PNM_FORMAT_TYPE(format) == PPM_FORMAT) ? TRUE: FALSE; + + if (n > 0) + { + if (w != width || h != height || c != color) + { + set_error (_("Format of image frame `%s' doesn't match."), + filename ? filename : "<stdin>"); + return NULL; + } + } + else + { + w = width; + h = height; + c = color; + } + Free (filename); + } + wi->frames = n; + wi->width = w; + wi->height = h; + wi->color = c; + } - /* + /* * Levels ... */ - { - unsigned lx, ly; + { + unsigned lx, ly; - lx = (unsigned) (log2 (wi->width - 1) + 1); - ly = (unsigned) (log2 (wi->height - 1) + 1); + lx = (unsigned) (log2 (wi->width - 1) + 1); + ly = (unsigned) (log2 (wi->height - 1) + 1); - wi->level = max (lx, ly) * 2 - ((ly == lx + 1) ? 1 : 0); - } + wi->level = max (lx, ly) * 2 - ((ly == lx + 1) ? 1 : 0); + } - c = Calloc (1, sizeof (coding_t)); + c = Calloc (1, sizeof (coding_t)); - c->options = *options; - c->options.lc_min_level = max (options->lc_min_level, 3); - c->options.lc_max_level = min (options->lc_max_level, wi->level - 1); + c->options = *options; + c->options.lc_min_level = max (options->lc_min_level, 3); + c->options.lc_max_level = min (options->lc_max_level, wi->level - 1); - c->tiling = alloc_tiling (options->tiling_method, - options->tiling_exponent, wi->level); + c->tiling = alloc_tiling (options->tiling_method, + options->tiling_exponent, wi->level); - if (wi->frames > 1 && c->tiling->exponent > 0) - { - c->tiling->exponent = 0; - warning (_("Image tiling valid only with still image compression.")); - } + if (wi->frames > 1 && c->tiling->exponent > 0) + { + c->tiling->exponent = 0; + warning (_("Image tiling valid only with still image compression.")); + } - if (c->options.lc_max_level >= wi->level - c->tiling->exponent) - { - message ("'max_level' changed from %d to %d due to image tiling level.", - c->options.lc_max_level, wi->level - c->tiling->exponent - 1); - c->options.lc_max_level = wi->level - c->tiling->exponent - 1; - } + if (c->options.lc_max_level >= wi->level - c->tiling->exponent) + { + message ("'max_level' changed from %d to %d " + "due to image tiling level.", + c->options.lc_max_level, wi->level - c->tiling->exponent - 1); + c->options.lc_max_level = wi->level - c->tiling->exponent - 1; + } - if (c->options.lc_min_level > c->options.lc_max_level) - c->options.lc_min_level = c->options.lc_max_level; + if (c->options.lc_min_level > c->options.lc_max_level) + c->options.lc_min_level = c->options.lc_max_level; - /* - * p_min_level, p_max_level min and max level for ND/MC prediction - * [p_min_level, p_max_level] must be a subset of [min_level, max_level] ! - */ - wi->p_min_level = max (options->p_min_level, c->options.lc_min_level); - wi->p_max_level = min (options->p_max_level, c->options.lc_max_level); - if (wi->p_min_level > wi->p_max_level) - wi->p_min_level = wi->p_max_level; - - c->options.images_level = min (c->options.images_level, - c->options.lc_max_level - 1); + /* + * p_min_level, p_max_level min and max level for ND/MC prediction + * [p_min_level, p_max_level] must be a subset of [min_level, max_level] ! + */ + wi->p_min_level = max (options->p_min_level, c->options.lc_min_level); + wi->p_max_level = min (options->p_max_level, c->options.lc_max_level); + if (wi->p_min_level > wi->p_max_level) + wi->p_min_level = wi->p_max_level; + + c->options.images_level = min (c->options.images_level, + c->options.lc_max_level - 1); - c->products_level = max (0, ((signed int) c->options.lc_max_level - - (signed int) c->options.images_level - 1)); - c->pixels = Calloc (size_of_level (c->options.lc_max_level), - sizeof (real_t)); - c->images_of_state = Calloc (MAXSTATES, sizeof (real_t *)); - c->ip_images_state = Calloc (MAXSTATES, sizeof (real_t *)); - c->ip_states_state = Calloc (MAXSTATES * MAXLEVEL, sizeof (real_t *)); + c->products_level = max (0, ((signed int) c->options.lc_max_level + - (signed int) c->options.images_level - 1)); + c->pixels = Calloc (size_of_level (c->options.lc_max_level), + sizeof (real_t)); + c->images_of_state = Calloc (MAXSTATES, sizeof (real_t *)); + c->ip_images_state = Calloc (MAXSTATES, sizeof (real_t *)); + c->ip_states_state = Calloc (MAXSTATES * MAXLEVEL, sizeof (real_t *)); - debug_message ("Imageslevel :%d, Productslevel :%d", - c->options.images_level, c->products_level); - debug_message ("Memory : (%d + %d + %d * 'states') * 'states' + %d", - size_of_tree (c->options.images_level) * 4, - size_of_tree (c->products_level) * 4, - (c->options.lc_max_level - c->options.images_level), - size_of_level (c->options.lc_max_level)); + debug_message ("Imageslevel :%d, Productslevel :%d", + c->options.images_level, c->products_level); + debug_message ("Memory : (%d + %d + %d * 'states') * 'states' + %d", + size_of_tree (c->options.images_level) * 4, + size_of_tree (c->products_level) * 4, + (c->options.lc_max_level - c->options.images_level), + size_of_level (c->options.lc_max_level)); - /* + /* * Domain pools ... */ - c->domain_pool = NULL; - c->d_domain_pool = NULL; - - /* - * Coefficients model ... - */ - c->coeff = NULL; - c->d_coeff = NULL; - - /* - * Max. number of states and edges - */ - wi->max_states = max (min (options->max_states, MAXSTATES), 1); - c->options.max_elements = max (min (options->max_elements, MAXEDGES), 1); - - /* - * Title and comment strings - */ - wi->title = strdup (options->title); - wi->comment = strdup (options->comment); + c->domain_pool = NULL; + c->d_domain_pool = NULL; + + /* + * Coefficients model ... + */ + c->coeff = NULL; + c->d_coeff = NULL; + + /* + * Max. number of states and edges + */ + wi->max_states = max (min (options->max_states, MAXSTATES), 1); + c->options.max_elements = max (min (options->max_elements, MAXEDGES), 1); + + /* + * Title and comment strings + */ + wi->title = strdup (options->title); + wi->comment = strdup (options->comment); - /* - * Reduced precision format - */ - wi->rpf - = alloc_rpf (options->rpf_mantissa, options->rpf_range); - wi->dc_rpf - = alloc_rpf (options->dc_rpf_mantissa, options->dc_rpf_range); - wi->d_rpf - = alloc_rpf (options->d_rpf_mantissa, options->d_rpf_range); - wi->d_dc_rpf - = alloc_rpf (options->d_dc_rpf_mantissa, options->d_dc_rpf_range); + /* + * Reduced precision format + */ + wi->rpf + = alloc_rpf (options->rpf_mantissa, options->rpf_range); + wi->dc_rpf + = alloc_rpf (options->dc_rpf_mantissa, options->dc_rpf_range); + wi->d_rpf + = alloc_rpf (options->d_rpf_mantissa, options->d_rpf_range); + wi->d_dc_rpf + = alloc_rpf (options->d_dc_rpf_mantissa, options->d_dc_rpf_range); - /* - * Color image options ... - */ - wi->chroma_max_states = max (1, options->chroma_max_states); + /* + * Color image options ... + */ + wi->chroma_max_states = max (1, options->chroma_max_states); - /* + /* * Set up motion compensation struct. * p_min_level, p_max_level are also used for ND prediction */ - wi->search_range = options->search_range; - wi->fps = options->fps; - wi->half_pixel = options->half_pixel_prediction; - wi->cross_B_search = options->half_pixel_prediction; - wi->B_as_past_ref = options->B_as_past_ref; - wi->smoothing = options->smoothing; + wi->search_range = options->search_range; + wi->fps = options->fps; + wi->half_pixel = options->half_pixel_prediction; + wi->cross_B_search = options->half_pixel_prediction; + wi->B_as_past_ref = options->B_as_past_ref; + wi->smoothing = options->smoothing; - c->mt = alloc_motion (wi); + c->mt = alloc_motion (wi); - return c; + return c; } + + static void free_coder (coding_t *c) /* @@ -384,7 +377,7 @@ free_coder (coding_t *c) * No return value. * * Side effects: - * structure 'coder' is discarded. + * structure 'coder' is discarded. */ { free_tiling (c->tiling); @@ -397,285 +390,8 @@ free_coder (coding_t *c) Free (c); } -static char * -get_input_image_name (char const * const *templptr, unsigned ith_image) -/* - * Construct the i-th image-name using templates. - * If the template contains a '[' it must be of the form - * "prefix[start-end{+,-}step]suffix" - * where "{+,-}step" is optional. - * Leading zeros of "start" are significant. - * - * Example: - * "image0[12-01-1].pgm" yields image012.pgm, image011.pgm, ..., image001.pgm - * - * Return value: - * ptr to name of image 'ith_image' or NULL if ith_image is out of range. - */ -{ - while (*templptr) - { - const char *template = *templptr++; - char *s; - - if (!(s = strchr (template, '['))) /* no template, just a filename */ - { - if (ith_image == 0) - return strdup (template); - else - ith_image--; - } - else /* template parser */ - { - unsigned n_digits; /* # of digits in image name no. */ - char *s2; - char *suffix; /* characters after template end */ - char prefix [MAXSTRLEN]; /* chars up to the template start */ - unsigned first; /* first image number */ - unsigned last; /* last image number */ - int image_num; /* current image number */ - int increment = 1; - int dummy; - - strcpy (prefix, template); - prefix [s - template] = '\0'; - - for (s2 = ++s, n_digits = 0; ISDIGIT (*s2); s2++, n_digits++) - ; - if (sscanf (s, "%d", &dummy) == 0 || dummy < 0) - error ("Input name template conversion failure.\n" - "Check spelling of template."); - first = (unsigned) dummy; - - if (*s2++ != '-') - error ("Input name template conversion failure.\n" - "Check spelling of template."); - - for (s = s2; ISDIGIT (*s2); s2++) - ; - if (sscanf (s, "%d", &dummy) == 0 || dummy < 0) - error ("Input name template conversion failure.\n" - "Check spelling of template."); - last = (unsigned) dummy; - - if (*s2 == '+' || *s2 == '-') - { - for (s = s2++; ISDIGIT (*s2); s2++) - ; - if (sscanf (s, "%d", &increment) == 0) - error ("Input name template conversion failure.\n" - "Check spelling of template."); - } - if (*s2 != ']') - error ("Input name template conversion failure.\n" - "Check spelling of template."); - suffix = s2 + 1; - - image_num = first + increment * ith_image; - if (image_num < 0) - error ("Input name template conversion failure.\n" - "Check spelling of template."); - - if ((increment > 0 && (unsigned) image_num > last) || - (increment <= 0 && (unsigned) image_num < last)) - { - /* TODO: check this */ - ith_image -= (last - first) / increment + 1; - } - else - { - char formatstr [MAXSTRLEN]; /* format string for image filename */ - char image_name [MAXSTRLEN]; /* image file name to be composed */ - - strcpy (formatstr, "%s%0?d%s"); - formatstr [4] = '0' + (char) n_digits; - sprintf (image_name, formatstr, prefix, image_num, suffix); - return strdup (image_name); - } - } - } - return NULL; -} - -static void -video_coder (char const * const *image_template, bitfile_t *output, - wfa_t *wfa, coding_t *c) -/* - * Toplevel function to encode a sequence of video frames specified - * by 'image_template'. The output is written to stream 'output'. - * Coding options are given by 'c'. - * - * No return value. - */ -{ - unsigned display; /* picture number in display order */ - int future_display; /* number of future reference */ - int frame; /* current frame number */ - char *image_name; /* image name of current frame */ - image_t *reconst = NULL; /* decoded reference image */ - bool_t future_frame = NO; /* YES if last frame was in future */ - - debug_message ("Generating %d WFA's ...", wfa->wfainfo->frames); - - future_display = -1; - frame = -1; - display = 0; - - while ((image_name = get_input_image_name (image_template, display))) - { - frame_type_e type; /* current frame type: I, B, P */ - - /* - * Determine type of next frame. - * Skip already coded frames (future reference!) - */ - if (display == 0 && !c->options.reference_filename) - type = I_FRAME; /* Force first frame to be intra */ - else - type = pattern2type (display, c->options.pattern); - - if (type != I_FRAME && c->options.reference_filename) - /* Load reference from disk */ - { - debug_message ("Reading reference frame `%s'.", - c->options.reference_filename); - reconst = read_image (c->options.reference_filename); - c->options.reference_filename = NULL; - } - if ((int) display == future_display) /* Skip already coded future ref */ - { - display++; - continue; - } - else if (type == B_FRAME && (int) display > future_display) - { - unsigned i = display; - /* - * Search for future reference - */ - while (type == B_FRAME) - { - char *name; /* image name of future frame */ - - i++; - name = get_input_image_name (image_template, i); - - if (!name) /* Force last valid frame to be 'P' */ - { - future_display = i - 1; - type = P_FRAME; - } - else - { - future_display = i; - image_name = name; - type = pattern2type (i, c->options.pattern); - } - frame = future_display; - } - } - else - { - frame = display; - display++; - } - - debug_message ("Coding \'%s\' [%c-frame].", image_name, - type == I_FRAME ? 'I' : (type == P_FRAME ? 'P' : 'B')); - - /* - * Depending on current frame type update past and future frames - * which are needed as reference frames. - */ - c->mt->frame_type = type; - if (type == I_FRAME) - { - if (c->mt->past) /* discard past frame */ - free_image (c->mt->past); - c->mt->past = NULL; - if (c->mt->future) /* discard future frame */ - free_image (c->mt->future); - c->mt->future = NULL; - if (reconst) /* discard current frame */ - free_image (reconst); - reconst = NULL; - } - else if (type == P_FRAME) - { - if (c->mt->past) /* discard past frame */ - free_image (c->mt->past); - c->mt->past = reconst; /* past frame <- current frame */ - reconst = NULL; - if (c->mt->future) /* discard future frame */ - free_image (c->mt->future); - c->mt->future = NULL; - } - else /* B_FRAME */ - { - if (future_frame) /* last frame was future frame */ - { - if (c->mt->future) /* discard future frame */ - free_image (c->mt->future); - c->mt->future = reconst; /* future frame <- current frame */ - reconst = NULL; - } - else - { - if (wfa->wfainfo->B_as_past_ref == YES) - { - if (c->mt->past) /* discard past frame */ - free_image (c->mt->past); - c->mt->past = reconst; /* past frame <- current frame */ - reconst = NULL; - } - else - { - if (reconst) /* discard current frame */ - free_image (reconst); - reconst = NULL; - } - } - } - - /* - * Start WFA coding of current frame - */ - future_frame = frame == future_display; - c->mt->number = frame; - c->mt->original = read_image (image_name); - if (c->tiling->exponent && type == I_FRAME) - perform_tiling (c->mt->original, c->tiling); - - frame_coder (wfa, c, output); - - /* - * Regenerate image: - * 1. Compute approximation of WFA ranges (real image bintree order) - * 2. Generate byte image in rasterscan order - * 3. Apply motion compensation - */ - reconst = decode_image (wfa->wfainfo->width, wfa->wfainfo->height, - FORMAT_4_4_4, NULL, wfa); - - if (type != I_FRAME) - restore_mc (0, reconst, c->mt->past, c->mt->future, wfa); - if (c->mt->original) - free_image (c->mt->original); - c->mt->original = NULL; - - remove_states (wfa->basis_states, wfa); /* Clear WFA structure */ - } - if (reconst) - free_image (reconst); - if (c->mt->future) - free_image (c->mt->future); - if (c->mt->past) - free_image (c->mt->past); - if (c->mt->original) - free_image (c->mt->original); -} static frame_type_e pattern2type (unsigned frame, const char *pattern) @@ -700,6 +416,72 @@ pattern2type (unsigned frame, const char *pattern) return retval; } + + +static void +print_statistics (char c, real_t costs, const wfa_t *wfa, const image_t *image, + const range_t *range) +{ + unsigned max_level, min_level, state, label, lincomb; + + for (max_level = 0, min_level = MAXLEVEL, state = wfa->basis_states; + state < wfa->states; state++) + { + for (lincomb = 0, label = 0; label < MAXLABELS; label++) + lincomb += isrange(wfa->tree[state][label]) ? 1 : 0; + + if (lincomb) + { + max_level = max (max_level, + (unsigned) (wfa->level_of_state [state] - 1)); + min_level = min (min_level, + (unsigned) (wfa->level_of_state [state] - 1)); + } + } + debug_message ("Image partitioning: maximum level %d , minimum level %d", + max_level, min_level); + debug_message ("WFA contains %d states (%d basis states).", + wfa->states, wfa->basis_states); + debug_message ("Estimated error: %.2f (RMSE: %.2f, PSNR: %.2f dB).", + (double) range->err, + sqrt (range->err / image->width / image->height), + 10 * log ( 255.0 * 255.0 / + (range->err / image->width / image->height)) + / log (10.0)); + debug_message ("Estimated filesize: %.0f bits (%.0f bytes).", + (double) (range->tree_bits + range->matrix_bits + + range->weights_bits + + range->mv_tree_bits + range->mv_coord_bits + + range->nd_tree_bits + range->nd_weights_bits), + (double) (range->tree_bits + range->matrix_bits + + range->weights_bits + range->mv_tree_bits + + range->mv_coord_bits + range->nd_tree_bits + + range->nd_weights_bits) / 8); + if (c) + debug_message ("(%cT: %.0f, %cM: %.0f, %cW: %.0f, %cMC: %.0f, " + "%cMV: %.0f, %cNT: %.0f, %cNW: %.0f.)", + c, (double) range->tree_bits, + c, (double) range->matrix_bits, + c, (double) range->weights_bits, + c, (double) range->mv_tree_bits, + c, (double) range->mv_coord_bits, + c, (double) range->nd_tree_bits, + c, (double) range->nd_weights_bits); + else + debug_message ("(T: %.0f, M: %.0f, W: %.0f, MC: %.0f, MV: %.0f, " + "NT: %.0f, NW: %.0f.)", + (double) range->tree_bits, + (double) range->matrix_bits, + (double) range->weights_bits, + (double) range->mv_tree_bits, + (double) range->mv_coord_bits, + (double) range->nd_tree_bits, + (double) range->nd_weights_bits); + debug_message ("Total costs : %.2f", (double) costs); +} + + + static void frame_coder (wfa_t *wfa, coding_t *c, bitfile_t *output) /* @@ -712,9 +494,9 @@ frame_coder (wfa_t *wfa, coding_t *c, bitfile_t *output) */ { unsigned state; - range_t range; /* first range == the entire image */ - real_t costs; /* total costs (minimized quantity) */ - unsigned bits; /* number of bits written on disk */ + range_t range; /* first range == the entire image */ + real_t costs; /* total costs (minimized quantity) */ + unsigned bits; /* number of bits written on disk */ clock_t ptimer; prg_timer (&ptimer, START); @@ -726,48 +508,48 @@ frame_coder (wfa_t *wfa, coding_t *c, bitfile_t *output) c->domain_pool = alloc_domain_pool (c->options.id_domain_pool, - wfa->wfainfo->max_states, - c->options.max_elements, wfa); + wfa->wfainfo->max_states, + c->options.max_elements, wfa); c->d_domain_pool = alloc_domain_pool ((c->options.prediction - || c->mt->frame_type != I_FRAME) - ? c->options.id_d_domain_pool : "constant", - wfa->wfainfo->max_states, - c->options.max_elements, wfa); + || c->mt->frame_type != I_FRAME) + ? c->options.id_d_domain_pool : "constant", + wfa->wfainfo->max_states, + c->options.max_elements, wfa); c->coeff = alloc_coeff_model (c->options.id_rpf_model, - wfa->wfainfo->rpf, - wfa->wfainfo->dc_rpf, - c->options.lc_min_level, - c->options.lc_max_level); + wfa->wfainfo->rpf, + wfa->wfainfo->dc_rpf, + c->options.lc_min_level, + c->options.lc_max_level); c->d_coeff = alloc_coeff_model (c->options.id_d_rpf_model, - wfa->wfainfo->d_rpf, - wfa->wfainfo->d_dc_rpf, - c->options.lc_min_level, - c->options.lc_max_level); + wfa->wfainfo->d_rpf, + wfa->wfainfo->d_dc_rpf, + c->options.lc_min_level, + c->options.lc_max_level); - if (!c->mt->original->color) /* grayscale image */ + if (!c->mt->original->color) /* grayscale image */ { memset (&range, 0, sizeof (range_t)); range.level = wfa->wfainfo->level; costs = subdivide (MAXCOSTS, GRAY, RANGE, &range, wfa, c, - c->options.prediction || c->mt->frame_type != I_FRAME, - NO); + c->options.prediction || c->mt->frame_type != I_FRAME, + NO); if (c->options.progress_meter != FIASCO_PROGRESS_NONE) - message (""); + message (""); - if (isrange (range.tree)) /* entire image is approx. by lc? */ - error ("No root state generated!"); + if (isrange (range.tree)) /* entire image is approx. by lc? */ + error ("No root state generated!"); else - wfa->root_state = range.tree; + wfa->root_state = range.tree; print_statistics ('\0', costs, wfa, c->mt->original, &range); } else { int YCb_node = -1; - int tree [3]; /* 3 root states of each color comp. */ + int tree [3]; /* 3 root states of each color comp. */ color_e band; /* @@ -781,62 +563,62 @@ frame_coder (wfa_t *wfa, coding_t *c, bitfile_t *output) */ for (band = first_band (YES); band <= last_band (YES) ; band++) { - debug_message ("Encoding color component %d", band); - tree [band] = RANGE; - if (band == Cb) - { - unsigned min_level; - - c->domain_pool->chroma (wfa->wfainfo->chroma_max_states, wfa, - c->domain_pool->model); - /* - * Don't use a finer partioning for the chrominancy bands than for - * the luminancy band. - */ - for (min_level = MAXLEVEL, state = wfa->basis_states; - state < wfa->states; state++) - { - unsigned lincomb, label; - - for (lincomb = 0, label = 0; label < MAXLABELS; label++) - lincomb += isrange (wfa->tree [state][label]) ? 1 : 0; - if (lincomb) - min_level = min (min_level, - (unsigned) (wfa->level_of_state [state] - - 1)); - } - c->options.lc_min_level = min_level; - if (c->mt->frame_type != I_FRAME) /* subtract mc of luminance */ - subtract_mc (c->mt->original, c->mt->past, c->mt->future, wfa); - } - - memset (&range, 0, sizeof (range_t)); - range.level = wfa->wfainfo->level; - - costs = subdivide (MAXCOSTS, band, tree [Y], &range, wfa, c, - c->mt->frame_type != I_FRAME && band == Y, NO); - if (c->options.progress_meter != FIASCO_PROGRESS_NONE) - message (""); - { - char colors [] = {'Y', 'B', 'R'}; - - print_statistics (colors [band], costs, wfa, - c->mt->original, &range); - } - - if (isrange (range.tree)) /* whole image is approx. by a l.c. */ - error ("No root state generated for color component %d!", band); - else - tree[band] = range.tree; - - if (band == Cb) - { - wfa->tree [wfa->states][0] = tree[Y]; - wfa->tree [wfa->states][1] = tree[Cb]; - YCb_node = wfa->states; - append_state (YES, compute_final_distribution (wfa->states, wfa), - wfa->wfainfo->level + 1, wfa, c); - } + debug_message ("Encoding color component %d", band); + tree [band] = RANGE; + if (band == Cb) + { + unsigned min_level; + + c->domain_pool->chroma (wfa->wfainfo->chroma_max_states, wfa, + c->domain_pool->model); + /* + * Don't use a finer partioning for the chrominancy bands than for + * the luminancy band. + */ + for (min_level = MAXLEVEL, state = wfa->basis_states; + state < wfa->states; state++) + { + unsigned lincomb, label; + + for (lincomb = 0, label = 0; label < MAXLABELS; label++) + lincomb += isrange (wfa->tree [state][label]) ? 1 : 0; + if (lincomb) + min_level = min (min_level, + (unsigned) (wfa->level_of_state [state] + - 1)); + } + c->options.lc_min_level = min_level; + if (c->mt->frame_type != I_FRAME) /* subtract mc of luminance */ + subtract_mc (c->mt->original, c->mt->past, c->mt->future, wfa); + } + + memset (&range, 0, sizeof (range_t)); + range.level = wfa->wfainfo->level; + + costs = subdivide (MAXCOSTS, band, tree [Y], &range, wfa, c, + c->mt->frame_type != I_FRAME && band == Y, NO); + if (c->options.progress_meter != FIASCO_PROGRESS_NONE) + message (""); + { + char colors [] = {'Y', 'B', 'R'}; + + print_statistics (colors [band], costs, wfa, + c->mt->original, &range); + } + + if (isrange (range.tree)) /* whole image is approx. by a l.c. */ + error ("No root state generated for color component %d!", band); + else + tree[band] = range.tree; + + if (band == Cb) + { + wfa->tree [wfa->states][0] = tree[Y]; + wfa->tree [wfa->states][1] = tree[Cb]; + YCb_node = wfa->states; + append_state (YES, compute_final_distribution (wfa->states, wfa), + wfa->wfainfo->level + 1, wfa, c); + } } /* * generate two virtual states (*) @@ -850,11 +632,11 @@ frame_coder (wfa_t *wfa, coding_t *c, bitfile_t *output) wfa->tree [wfa->states][0] = tree[Cr]; wfa->tree [wfa->states][1] = RANGE; append_state (YES, compute_final_distribution (wfa->states, wfa), - wfa->wfainfo->level + 1, wfa, c); + wfa->wfainfo->level + 1, wfa, c); wfa->tree[wfa->states][0] = YCb_node; wfa->tree[wfa->states][1] = wfa->states - 1; append_state (YES, compute_final_distribution (wfa->states, wfa), - wfa->wfainfo->level + 2, wfa, c); + wfa->wfainfo->level + 2, wfa, c); wfa->root_state = wfa->states - 1; } @@ -865,22 +647,22 @@ frame_coder (wfa_t *wfa, coding_t *c, bitfile_t *output) if (c->images_of_state [state]) { - Free (c->images_of_state [state]); - c->images_of_state [state] = NULL; + Free (c->images_of_state [state]); + c->images_of_state [state] = NULL; } if (c->ip_images_state [state]) { - Free (c->ip_images_state [state]); - c->ip_images_state [state] = NULL; + Free (c->ip_images_state [state]); + c->ip_images_state [state] = NULL; } for (level = c->options.images_level + 1; - level <= c->options.lc_max_level; - level++) - if (c->ip_states_state [state][level]) - { - Free (c->ip_states_state [state][level]); - c->ip_states_state [state][level] = NULL; - } + level <= c->options.lc_max_level; + level++) + if (c->ip_states_state [state][level]) + { + Free (c->ip_states_state [state][level]); + c->ip_states_state [state][level] = NULL; + } } @@ -889,11 +671,11 @@ frame_coder (wfa_t *wfa, coding_t *c, bitfile_t *output) bits = bits_processed (output) - bits; debug_message ("Total number of bits written: %d (%d bytes, %5.3f bpp)", - bits, bits >> 3, - bits / (double) (c->mt->original->height - * c->mt->original->width)); + bits, bits >> 3, + bits / (double) (c->mt->original->height + * c->mt->original->width)); debug_message ("Total encoding time (real): %d sec", - prg_timer (&ptimer, STOP) / 1000); + prg_timer (&ptimer, STOP) / 1000); c->domain_pool->free (c->domain_pool); c->d_domain_pool->free (c->d_domain_pool); @@ -902,64 +684,356 @@ frame_coder (wfa_t *wfa, coding_t *c, bitfile_t *output) c->d_coeff->free (c->d_coeff); } + + static void -print_statistics (char c, real_t costs, const wfa_t *wfa, const image_t *image, - const range_t *range) +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) +/* + * Toplevel function to encode a sequence of video frames specified + * by 'image_template'. The output is written to stream 'output'. + * Coding options are given by 'c'. + * + * No return value. + */ { - unsigned max_level, min_level, state, label, lincomb; + unsigned display; /* picture number in display order */ + int future_display; /* number of future reference */ + int frame; /* current frame number */ + char *image_name; + /* image name of current frame. File name or "-" for Standard Input */ + image_t *reconst = NULL; /* decoded reference image */ + bool_t future_frame = NO; /* YES if last frame was in future */ - for (max_level = 0, min_level = MAXLEVEL, state = wfa->basis_states; - state < wfa->states; state++) - { - for (lincomb = 0, label = 0; label < MAXLABELS; label++) - lincomb += isrange(wfa->tree[state][label]) ? 1 : 0; - - if (lincomb) - { - max_level = max (max_level, - (unsigned) (wfa->level_of_state [state] - 1)); - min_level = min (min_level, - (unsigned) (wfa->level_of_state [state] - 1)); - } - } - debug_message ("Image partitioning: maximum level %d , minimum level %d", - max_level, min_level); - debug_message ("WFA contains %d states (%d basis states).", - wfa->states, wfa->basis_states); - debug_message ("Estimated error: %.2f (RMSE: %.2f, PSNR: %.2f dB).", - (double) range->err, - sqrt (range->err / image->width / image->height), - 10 * log ( 255.0 * 255.0 / - (range->err / image->width / image->height)) - / log (10.0)); - debug_message ("Estimated filesize: %.0f bits (%.0f bytes).", - (double) (range->tree_bits + range->matrix_bits - + range->weights_bits - + range->mv_tree_bits + range->mv_coord_bits - + range->nd_tree_bits + range->nd_weights_bits), - (double) (range->tree_bits + range->matrix_bits - + range->weights_bits + range->mv_tree_bits - + range->mv_coord_bits + range->nd_tree_bits - + range->nd_weights_bits) / 8); - if (c) - debug_message ("(%cT: %.0f, %cM: %.0f, %cW: %.0f, %cMC: %.0f, " - "%cMV: %.0f, %cNT: %.0f, %cNW: %.0f.)", - c, (double) range->tree_bits, - c, (double) range->matrix_bits, - c, (double) range->weights_bits, - c, (double) range->mv_tree_bits, - c, (double) range->mv_coord_bits, - c, (double) range->nd_tree_bits, - c, (double) range->nd_weights_bits); - else - debug_message ("(T: %.0f, M: %.0f, W: %.0f, MC: %.0f, MV: %.0f, " - "NT: %.0f, NW: %.0f.)", - (double) range->tree_bits, - (double) range->matrix_bits, - (double) range->weights_bits, - (double) range->mv_tree_bits, - (double) range->mv_coord_bits, - (double) range->nd_tree_bits, - (double) range->nd_weights_bits); - debug_message ("Total costs : %.2f", (double) costs); + debug_message ("Generating %d WFA's ...", wfa->wfainfo->frames); + + future_display = -1; + frame = -1; + display = 0; + + while ((image_name = get_input_image_name (image_template, display))) + { + frame_type_e type; /* current frame type: I, B, P */ + + /* + * Determine type of next frame. + * Skip already coded frames (future reference!) + */ + if (display == 0 && !c->options.reference_filename) + type = I_FRAME; /* Force first frame to be intra */ + else + type = pattern2type (display, c->options.pattern); + + if (type != I_FRAME && c->options.reference_filename) + /* Load reference from disk */ + { + debug_message ("Reading reference frame `%s'.", + c->options.reference_filename); + reconst = read_image_file (c->options.reference_filename); + c->options.reference_filename = NULL; + } + if ((int) display == future_display) + { + /* Skip already coded future ref */ + display++; + continue; + } + else if (type == B_FRAME && (int) display > future_display) + { + unsigned i = display; + /* + * Search for future reference + */ + while (type == B_FRAME) + { + char *name; /* image name of future frame */ + + i++; + name = get_input_image_name (image_template, i); + + if (!name) /* Force last valid frame to be 'P' */ + { + future_display = i - 1; + type = P_FRAME; + } + else + { + future_display = i; + image_name = name; + type = pattern2type (i, c->options.pattern); + } + frame = future_display; + } + } + else + { + frame = display; + display++; + } + + debug_message ("Coding \'%s\' [%c-frame].", image_name, + type == I_FRAME ? 'I' : (type == P_FRAME ? 'P' : 'B')); + + /* + * Depending on current frame type update past and future frames + * which are needed as reference frames. + */ + c->mt->frame_type = type; + if (type == I_FRAME) + { + if (c->mt->past) /* discard past frame */ + free_image (c->mt->past); + c->mt->past = NULL; + if (c->mt->future) /* discard future frame */ + free_image (c->mt->future); + c->mt->future = NULL; + if (reconst) /* discard current frame */ + free_image (reconst); + reconst = NULL; + } + else if (type == P_FRAME) + { + if (c->mt->past) /* discard past frame */ + free_image (c->mt->past); + c->mt->past = reconst; /* past frame <- current frame */ + reconst = NULL; + if (c->mt->future) /* discard future frame */ + free_image (c->mt->future); + c->mt->future = NULL; + } + else /* B_FRAME */ + { + if (future_frame) /* last frame was future frame */ + { + if (c->mt->future) /* discard future frame */ + free_image (c->mt->future); + c->mt->future = reconst; /* future frame <- current frame */ + reconst = NULL; + } + else + { + if (wfa->wfainfo->B_as_past_ref == YES) + { + if (c->mt->past) /* discard past frame */ + free_image (c->mt->past); + c->mt->past = reconst; /* past frame <- current frame */ + reconst = NULL; + } + else + { + if (reconst) /* discard current frame */ + free_image (reconst); + reconst = NULL; + } + } + } + + /* + * Start WFA coding of current frame + */ + future_frame = frame == future_display; + c->mt->number = frame; + + if (streq(image_name, "-")) + c->mt->original = read_image_stream(stdin, + stdinwidth, stdinheight, + stdinmaxval, stdinformat); + else + c->mt->original = read_image_file(image_name); + + if (c->tiling->exponent && type == I_FRAME) + perform_tiling (c->mt->original, c->tiling); + + frame_coder (wfa, c, output); + + /* + * Regenerate image: + * 1. Compute approximation of WFA ranges (real image bintree order) + * 2. Generate byte image in rasterscan order + * 3. Apply motion compensation + */ + reconst = decode_image (wfa->wfainfo->width, wfa->wfainfo->height, + FORMAT_4_4_4, NULL, wfa); + + if (type != I_FRAME) + restore_mc (0, reconst, c->mt->past, c->mt->future, wfa); + + if (c->mt->original) + free_image (c->mt->original); + c->mt->original = NULL; + + remove_states (wfa->basis_states, wfa); /* Clear WFA structure */ + } + + if (reconst) + free_image (reconst); + if (c->mt->future) + free_image (c->mt->future); + if (c->mt->past) + free_image (c->mt->past); + if (c->mt->original) + free_image (c->mt->original); +} + + + +static void +read_stdin_header(const char * const * const template, + unsigned int * const widthP, + unsigned int * const heightP, + xelval * const maxvalP, + int * const formatP) +/* Read the PNM header from the Standard Input stream, if 'template' says + one of the images is to come from Standard Input. + + Return the contents of that stream as *widthP, etc. +*/ +{ + unsigned int i; + bool endOfList; + bool stdinFound; + + for (i = 0, stdinFound = FALSE, endOfList = FALSE; !endOfList; ++i) { + const char * const name = get_input_image_name(template, i); + + if (!name) + endOfList = TRUE; + else { + if (streq(name, "-")) + stdinFound = TRUE; + } + } + + if (stdinFound) { + int width, height; + + pnm_readpnminit(stdin, &width, &height, maxvalP, formatP); + + *widthP = width; + *heightP = height; + } } + + + +/***************************************************************************** + + public code + +*****************************************************************************/ + +int +fiasco_coder (char const * const *inputname, const char *outputname, + float quality, const fiasco_c_options_t *options) +/* + * FIASCO coder. + * Encode image or video frames given by the array of filenames `inputname' + * and write to the outputfile `outputname'. + * If 'inputname' = NULL or + * 'inputname [0]' == NULL or + * 'inputname [0]' == "-", read standard input. + * If 'outputname' == NULL or "-", write on standard output. + * 'quality' defines the approximation quality and is 1 (worst) to 100 (best). + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + try + { + char const * const default_input [] = {"-", NULL}; + fiasco_c_options_t *default_options = NULL; + const c_options_t *cop; + char const * const *template; + unsigned int stdinheight, stdinwidth; + xelval stdinmaxval; + int stdinformat; + + /* + * Check parameters + */ + if (!inputname || !inputname [0] || streq (inputname [0], "-")) + template = default_input; + else + template = inputname; + + if (quality <= 0) + { + set_error (_("Compression quality has to be positive.")); + return 0; + } + else if (quality >= 100) + { + warning (_("Quality typically is 1 (worst) to 100 (best).\n" + "Be prepared for a long running time.")); + } + + if (options) + { + cop = cast_c_options ((fiasco_c_options_t *) options); + if (!cop) + return 0; + } + else + { + default_options = fiasco_c_options_new (); + cop = cast_c_options (default_options); + } + + read_stdin_header(template, &stdinwidth, &stdinheight, + &stdinmaxval, &stdinformat); + + /* + * Open output stream and initialize WFA + */ + { + bitfile_t *output = open_bitfile (outputname, "FIASCO_DATA", + WRITE_ACCESS); + if (!output) + { + set_error (_("Can't write outputfile `%s'.\n%s"), + outputname ? outputname : "<stdout>", + get_system_error ()); + if (default_options) + fiasco_c_options_delete (default_options); + return 0; + } + else + { + wfa_t *wfa = alloc_wfa (YES); + coding_t *c = alloc_coder(template, cop, wfa->wfainfo, + stdinwidth, stdinheight, + stdinmaxval, stdinformat); + + read_basis (cop->basis_name, wfa); + append_basis_states (wfa->basis_states, wfa, c); + + c->price = 128 * 64 / quality; + + video_coder (template, output, wfa, c, + stdinwidth, stdinheight, stdinmaxval, + stdinformat); + + close_bitfile (output); + free_wfa (wfa); + free_coder (c); + + if (default_options) + fiasco_c_options_delete (default_options); + } + } + return 1; + } + catch + { + return 0; + } +} + diff --git a/converter/other/fiasco/codec/decoder.c b/converter/other/fiasco/codec/decoder.c index c3982617..ab06dd2e 100644 --- a/converter/other/fiasco/codec/decoder.c +++ b/converter/other/fiasco/codec/decoder.c @@ -1,9 +1,9 @@ /* - * decode.c: Decoding of an image represented by a WFA + * decode.c: Decoding of an image represented by a WFA * - * Written by: Ullrich Hafner - * Michael Unger - * + * Written by: Ullrich Hafner + * Michael Unger + * * This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec) * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> */ @@ -15,12 +15,13 @@ * $State: Exp $ */ +#include "pm_config.h" #include "config.h" #if HAVE_STRING_H -# include <string.h> +# include <string.h> #else /* not HAVE_STRING_H */ -# include <strings.h> +# include <strings.h> #endif /* not HAVE_STRING_H */ #include "types.h" @@ -37,33 +38,33 @@ /***************************************************************************** - prototypes + prototypes *****************************************************************************/ static void compute_state_images (unsigned frame_level, word_t **simg, - const u_word_t *offset, const wfa_t *wfa); + const u_word_t *offset, const wfa_t *wfa); static void free_state_images (unsigned max_level, bool_t color, word_t **state_image, - u_word_t *offset, const unsigned *root_state, - unsigned range_state, format_e format, const wfa_t *wfa); + u_word_t *offset, const unsigned *root_state, + unsigned range_state, format_e format, const wfa_t *wfa); static void alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, - const unsigned *root_state, unsigned range_state, - unsigned max_level, format_e format, const wfa_t *wfa); + const unsigned *root_state, unsigned range_state, + unsigned max_level, format_e format, const wfa_t *wfa); static void compute_actual_size (unsigned luminance_root, - unsigned *width, unsigned *height, const wfa_t *wfa); + unsigned *width, unsigned *height, const wfa_t *wfa); static void enlarge_image (int enlarge_factor, format_e format, unsigned y_root, - wfa_t *wfa); + wfa_t *wfa); static word_t * duplicate_state_image (const word_t *domain, unsigned offset, unsigned level); /***************************************************************************** - public code + public code *****************************************************************************/ @@ -75,7 +76,7 @@ alloc_video (bool_t store_wfa) * and future WFA if flag 'store_wfa' is TRUE. * * Return value: - * pointer to the new video structure + * pointer to the new video structure */ { video_t *video = Calloc (1, sizeof (video_t)); @@ -84,7 +85,7 @@ alloc_video (bool_t store_wfa) video->display = 0; video->future = video->sfuture = video->past - = video->frame = video->sframe = NULL; + = video->frame = video->sframe = NULL; if (store_wfa) { @@ -107,7 +108,7 @@ free_video (video_t *video) * No return value. * * Side effects: - * 'video' struct is discarded. + * 'video' struct is discarded. */ { if (video->past) @@ -132,9 +133,9 @@ free_video (video_t *video) image_t * get_next_frame (bool_t store_wfa, int enlarge_factor, - int smoothing, const char *reference_frame, - format_e format, video_t *video, dectimer_t *timer, - wfa_t *orig_wfa, bitfile_t *input) + int smoothing, const char *reference_frame, + format_e format, video_t *video, dectimer_t *timer, + wfa_t *orig_wfa, bitfile_t *input) /* * Get next frame of the WFA 'video' from stream 'input'. * 'orig_wfa' is the constant part of the WFA used by all frames. @@ -148,265 +149,265 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, * If 'timer' is not NULL, then accumulate running time statistics. * * Return value: - * pointer to decoded frame + * pointer to decoded frame * * Side effects: - * 'video' and 'timer' struct are modified. + * 'video' and 'timer' struct are modified. */ { - image_t *frame = NULL; /* current frame */ - image_t *sframe = NULL; /* current smoothed frame */ + image_t *frame = NULL; /* current frame */ + image_t *sframe = NULL; /* current smoothed frame */ bool_t current_frame_is_future_frame = NO; - if (video->future_display == video->display) + if (video->future_display == video->display) { /* * Future frame is already computed since it has been used * as reference frame. So just return the stored frame. */ if (video->frame) /* discard current frame */ - free_image (video->frame); + free_image (video->frame); video->frame = video->future; video->future = NULL; if (video->sframe) /* discard current (smoothed) frame */ - free_image (video->sframe); + free_image (video->sframe); video->sframe = video->sfuture; video->sfuture = NULL; if (store_wfa) - copy_wfa (video->wfa, video->wfa_future); + copy_wfa (video->wfa, video->wfa_future); video->display++; if (!store_wfa) - video->wfa = NULL; + video->wfa = NULL; } else { - do /* compute next frame(s) */ + do /* compute next frame(s) */ { - unsigned frame_number; /* current frame number */ - clock_t ptimer; - unsigned int stop_timer [3]; - wfa_t *tmp_wfa = NULL; - - if (!store_wfa) - video->wfa = orig_wfa; - else - { - tmp_wfa = alloc_wfa (NO); - copy_wfa (tmp_wfa, video->wfa); - copy_wfa (video->wfa, orig_wfa); - } + unsigned frame_number; /* current frame number */ + clock_t ptimer; + unsigned int stop_timer [3]; + wfa_t *tmp_wfa = NULL; + + if (!store_wfa) + video->wfa = orig_wfa; + else + { + tmp_wfa = alloc_wfa (NO); + copy_wfa (tmp_wfa, video->wfa); + copy_wfa (video->wfa, orig_wfa); + } - /* - * First step: read WFA from disk - */ - prg_timer (&ptimer, START); - frame_number = read_next_wfa (video->wfa, input); - stop_timer [0] = prg_timer (&ptimer, STOP); - if (timer) - { - timer->input [video->wfa->frame_type] += stop_timer [0]; - timer->frames [video->wfa->frame_type]++; - } + /* + * First step: read WFA from disk + */ + prg_timer (&ptimer, START); + frame_number = read_next_wfa (video->wfa, input); + stop_timer [0] = prg_timer (&ptimer, STOP); + if (timer) + { + timer->input [video->wfa->frame_type] += stop_timer [0]; + timer->frames [video->wfa->frame_type]++; + } - /* - * Read reference frame from disk if required - * (i.e., 1st frame is of type B or P) - */ - if (video->display == 0 && video->wfa->frame_type != I_FRAME) - { - if (!reference_frame) - error ("First frame is %c-frame but no " - "reference frame is given.", - video->wfa->frame_type == B_FRAME ? 'B' : 'P'); - - video->frame = read_image (reference_frame); - video->sframe = NULL; - } + /* + * Read reference frame from disk if required + * (i.e., 1st frame is of type B or P) + */ + if (video->display == 0 && video->wfa->frame_type != I_FRAME) + { + if (!reference_frame) + error ("First frame is %c-frame but no " + "reference frame is given.", + video->wfa->frame_type == B_FRAME ? 'B' : 'P'); + + video->frame = read_image_file (reference_frame); + video->sframe = NULL; + } - /* - * Depending on current frame type update past and future frames - */ - if (video->wfa->frame_type == I_FRAME) - { - if (video->past) /* discard past frame */ - free_image (video->past); - video->past = NULL; - if (video->future) /* discard future frame */ - free_image (video->future); - video->future = NULL; - if (video->sfuture) /* discard (smoothed) future frame */ - free_image (video->sfuture); - video->sfuture = NULL; - if (video->frame) /* discard current frame */ - free_image (video->frame); - video->frame = NULL; - if (video->sframe) /* discard current (smoothed) frame */ - free_image (video->sframe); - video->sframe = NULL; - } - else if (video->wfa->frame_type == P_FRAME) - { - if (video->past) /* discard past frame */ - free_image (video->past); - video->past = video->frame; /* past <- current frame */ - video->frame = NULL; - if (video->sframe) /* discard current (smoothed) frame */ - free_image (video->sframe); - video->sframe = NULL; - if (store_wfa) - copy_wfa (video->wfa_past, tmp_wfa); - if (video->future) /* discard future frame */ - free_image (video->future); - video->future = NULL; - if (video->sfuture) /* discard (smoothed) future frame */ - free_image (video->sfuture); - video->sfuture = NULL; - } - else /* B_FRAME */ - { - if (current_frame_is_future_frame) - { - if (video->future) /* discard future frame */ - free_image (video->future); - video->future = frame; /* future <- current frame */ - if (video->sfuture) /* discard (smoothed) future frame */ - free_image (video->sfuture); - video->sfuture = sframe; /* future <- current (smoothed) */ - if (store_wfa) - copy_wfa (video->wfa_future, tmp_wfa); - if (video->frame) /* discard current frame */ - free_image (video->frame); - video->frame = NULL; - if (video->sframe) /* discard current (smoothed) frame */ - free_image (video->sframe); - video->sframe = NULL; - frame = NULL; - sframe = NULL; - } - else - { - if (video->wfa->wfainfo->B_as_past_ref == YES) - { - if (video->past) /* discard past frame */ - free_image (video->past); - video->past = video->frame; /* past <- current frame */ - video->frame = NULL; - if (video->sframe) /* discard current (smoothed) frame */ - free_image (video->sframe); - video->sframe = NULL; - if (store_wfa) - copy_wfa (video->wfa_past, tmp_wfa); - } - else - { - if (video->frame) /* discard current */ - free_image (video->frame); - video->frame = NULL; - if (video->sframe) /* discard current (smoothed) frame */ - free_image (video->sframe); - video->sframe = NULL; - } - } - } - if (tmp_wfa) - free_wfa (tmp_wfa); - - current_frame_is_future_frame = NO; - /* - * Second step: decode image - * Optionally enlarge image if specified by option 'enlarge_factor'. - */ - { - unsigned orig_width, orig_height; - - stop_timer [0] = stop_timer [1] = stop_timer [2] = 0; - - enlarge_image (enlarge_factor, format, - (video->wfa->wfainfo->color - && format == FORMAT_4_2_0) - ? video->wfa->tree [video->wfa->tree [video->wfa->root_state][0]][0] : -1, video->wfa); - - if (enlarge_factor > 0) - { - orig_width = video->wfa->wfainfo->width << enlarge_factor; - orig_height = video->wfa->wfainfo->height << enlarge_factor; - } - else - { - orig_width = video->wfa->wfainfo->width >> - enlarge_factor; - orig_height = video->wfa->wfainfo->height >> - enlarge_factor; - if (orig_width & 1) - orig_width++; - if (orig_height & 1) - orig_height++; - } - - frame = decode_image (orig_width, orig_height, format, - timer != NULL ? stop_timer : NULL, - video->wfa); - if (timer) - { - timer->preprocessing [video->wfa->frame_type] += stop_timer [0]; - timer->decoder [video->wfa->frame_type] += stop_timer [1]; - timer->cleanup [video->wfa->frame_type] += stop_timer [2]; - } - } - - /* - * Third step: restore motion compensation - */ - if (video->wfa->frame_type != I_FRAME) - { - prg_timer (&ptimer, START); - restore_mc (enlarge_factor, frame, video->past, video->future, - video->wfa); - stop_timer [0] = prg_timer (&ptimer, STOP); - if (timer) - timer->motion [video->wfa->frame_type] += stop_timer [0]; - } - - /* - * Fourth step: smooth image along partitioning borders - */ - prg_timer (&ptimer, START); - if (smoothing < 0) /* smoothing not changed by user */ - smoothing = video->wfa->wfainfo->smoothing; - if (smoothing > 0 && smoothing <= 100) - { - sframe = clone_image (frame); - smooth_image (smoothing, video->wfa, sframe); - } - else - sframe = NULL; - - stop_timer [0] = prg_timer (&ptimer, STOP); - if (timer) - timer->smooth [video->wfa->frame_type] += stop_timer [0]; - - if (frame_number == video->display) - { - video->display++; - video->frame = frame; - video->sframe = sframe; - frame = NULL; - sframe = NULL; - } - else if (frame_number > video->display) - { - video->future_display = frame_number; - current_frame_is_future_frame = YES; - } + /* + * Depending on current frame type update past and future frames + */ + if (video->wfa->frame_type == I_FRAME) + { + if (video->past) /* discard past frame */ + free_image (video->past); + video->past = NULL; + if (video->future) /* discard future frame */ + free_image (video->future); + video->future = NULL; + if (video->sfuture) /* discard (smoothed) future frame */ + free_image (video->sfuture); + video->sfuture = NULL; + if (video->frame) /* discard current frame */ + free_image (video->frame); + video->frame = NULL; + if (video->sframe) /* discard current (smoothed) frame */ + free_image (video->sframe); + video->sframe = NULL; + } + else if (video->wfa->frame_type == P_FRAME) + { + if (video->past) /* discard past frame */ + free_image (video->past); + video->past = video->frame; /* past <- current frame */ + video->frame = NULL; + if (video->sframe) /* discard current (smoothed) frame */ + free_image (video->sframe); + video->sframe = NULL; + if (store_wfa) + copy_wfa (video->wfa_past, tmp_wfa); + if (video->future) /* discard future frame */ + free_image (video->future); + video->future = NULL; + if (video->sfuture) /* discard (smoothed) future frame */ + free_image (video->sfuture); + video->sfuture = NULL; + } + else /* B_FRAME */ + { + if (current_frame_is_future_frame) + { + if (video->future) /* discard future frame */ + free_image (video->future); + video->future = frame; /* future <- current frame */ + if (video->sfuture) /* discard (smoothed) future frame */ + free_image (video->sfuture); + video->sfuture = sframe; /* future <- current (smoothed) */ + if (store_wfa) + copy_wfa (video->wfa_future, tmp_wfa); + if (video->frame) /* discard current frame */ + free_image (video->frame); + video->frame = NULL; + if (video->sframe) /* discard current (smoothed) frame */ + free_image (video->sframe); + video->sframe = NULL; + frame = NULL; + sframe = NULL; + } + else + { + if (video->wfa->wfainfo->B_as_past_ref == YES) + { + if (video->past) /* discard past frame */ + free_image (video->past); + video->past = video->frame; /* past <- current frame */ + video->frame = NULL; + if (video->sframe) /* discard current (smoothed) frame */ + free_image (video->sframe); + video->sframe = NULL; + if (store_wfa) + copy_wfa (video->wfa_past, tmp_wfa); + } + else + { + if (video->frame) /* discard current */ + free_image (video->frame); + video->frame = NULL; + if (video->sframe) /* discard current (smoothed) frame */ + free_image (video->sframe); + video->sframe = NULL; + } + } + } + if (tmp_wfa) + free_wfa (tmp_wfa); + + current_frame_is_future_frame = NO; + /* + * Second step: decode image + * Optionally enlarge image if specified by option 'enlarge_factor'. + */ + { + unsigned orig_width, orig_height; + + stop_timer [0] = stop_timer [1] = stop_timer [2] = 0; + + enlarge_image (enlarge_factor, format, + (video->wfa->wfainfo->color + && format == FORMAT_4_2_0) + ? video->wfa->tree [video->wfa->tree [video->wfa->root_state][0]][0] : -1, video->wfa); + + if (enlarge_factor > 0) + { + orig_width = video->wfa->wfainfo->width << enlarge_factor; + orig_height = video->wfa->wfainfo->height << enlarge_factor; + } + else + { + orig_width = video->wfa->wfainfo->width >> - enlarge_factor; + orig_height = video->wfa->wfainfo->height >> - enlarge_factor; + if (orig_width & 1) + orig_width++; + if (orig_height & 1) + orig_height++; + } + + frame = decode_image (orig_width, orig_height, format, + timer != NULL ? stop_timer : NULL, + video->wfa); + if (timer) + { + timer->preprocessing [video->wfa->frame_type] += stop_timer [0]; + timer->decoder [video->wfa->frame_type] += stop_timer [1]; + timer->cleanup [video->wfa->frame_type] += stop_timer [2]; + } + } + + /* + * Third step: restore motion compensation + */ + if (video->wfa->frame_type != I_FRAME) + { + prg_timer (&ptimer, START); + restore_mc (enlarge_factor, frame, video->past, video->future, + video->wfa); + stop_timer [0] = prg_timer (&ptimer, STOP); + if (timer) + timer->motion [video->wfa->frame_type] += stop_timer [0]; + } + + /* + * Fourth step: smooth image along partitioning borders + */ + prg_timer (&ptimer, START); + if (smoothing < 0) /* smoothing not changed by user */ + smoothing = video->wfa->wfainfo->smoothing; + if (smoothing > 0 && smoothing <= 100) + { + sframe = clone_image (frame); + smooth_image (smoothing, video->wfa, sframe); + } + else + sframe = NULL; + + stop_timer [0] = prg_timer (&ptimer, STOP); + if (timer) + timer->smooth [video->wfa->frame_type] += stop_timer [0]; + + if (frame_number == video->display) + { + video->display++; + video->frame = frame; + video->sframe = sframe; + frame = NULL; + sframe = NULL; + } + else if (frame_number > video->display) + { + video->future_display = frame_number; + current_frame_is_future_frame = YES; + } - if (!store_wfa) - remove_states (video->wfa->basis_states, video->wfa); + if (!store_wfa) + remove_states (video->wfa->basis_states, video->wfa); } while (!video->frame); if (!store_wfa) - video->wfa = NULL; + video->wfa = NULL; } return video->sframe ? video->sframe : video->frame; @@ -414,7 +415,7 @@ get_next_frame (bool_t store_wfa, int enlarge_factor, image_t * decode_image (unsigned orig_width, unsigned orig_height, format_e format, - unsigned *dec_timer, const wfa_t *wfa) + unsigned *dec_timer, const wfa_t *wfa) /* * Compute image which is represented by the given 'wfa'. * 'orig_width'x'orig_height' gives the resolution of the image at @@ -422,20 +423,20 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format, * If 'dec_timer' is given, accumulate running time statistics. * * Return value: - * pointer to decoded image + * pointer to decoded image * * Side effects: - * '*dectimer' is changed if 'dectimer' != NULL. + * '*dectimer' is changed if 'dectimer' != NULL. */ { - unsigned root_state [3]; /* root of bintree for each band */ - unsigned width, height; /* computed image size */ - image_t *frame; /* regenerated frame */ - word_t **images; /* pointer to array of pointers - to state images */ - u_word_t *offsets; /* pointer to array of state image - offsets */ - unsigned max_level; /* max. level of state with approx. */ + unsigned root_state [3]; /* root of bintree for each band */ + unsigned width, height; /* computed image size */ + image_t *frame; /* regenerated frame */ + word_t **images; /* pointer to array of pointers + to state images */ + u_word_t *offsets; /* pointer to array of state image + offsets */ + unsigned max_level; /* max. level of state with approx. */ unsigned state; clock_t ptimer; @@ -458,14 +459,14 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format, */ for (max_level = 0, state = wfa->basis_states; state < wfa->states; state++) if (isedge (wfa->into [state][0][0]) || isedge (wfa->into [state][1][0])) - max_level = max (max_level, wfa->level_of_state [state]); + max_level = max (max_level, wfa->level_of_state [state]); /* * Allocate frame buffer for decoded image */ compute_actual_size (format == FORMAT_4_2_0 ? root_state [Y] : MAXSTATES, - &width, &height, wfa); + &width, &height, wfa); width = max (width, orig_width); height = max (height, orig_height); frame = alloc_image (width, height, wfa->wfainfo->color, format); @@ -480,7 +481,7 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format, wfa->level_of_state [wfa->tree[wfa->root_state][1]] = 128; } alloc_state_images (&images, &offsets, frame, root_state, 0, max_level, - format, wfa); + format, wfa); if (dec_timer) dec_timer [0] += prg_timer (&ptimer, STOP); @@ -498,38 +499,38 @@ decode_image (unsigned orig_width, unsigned orig_height, format_e format, */ prg_timer (&ptimer, START); free_state_images (max_level, frame->color, images, offsets, root_state, 0, - format, wfa); + format, wfa); /* * Crop decoded image if the image size differs. */ if (orig_width != width || orig_height != height) { - frame->height = orig_height; - frame->width = orig_width; - if (orig_width != width) + frame->height = orig_height; + frame->width = orig_width; + if (orig_width != width) { - color_e band; /* current color band */ - word_t *src, *dst; /* source and destination pointers */ - unsigned y; /* current row */ - - for (band = first_band (frame->color); - band <= last_band (frame->color); band++) - { - src = dst = frame->pixels [band]; - for (y = orig_height; y; y--) - { - memmove (dst, src, orig_width * sizeof (word_t)); - dst += orig_width; - src += width; - } - if (format == FORMAT_4_2_0 && band == Y) - { - orig_width >>= 1; - orig_height >>= 1; - width >>= 1; - } - } + color_e band; /* current color band */ + word_t *src, *dst; /* source and destination pointers */ + unsigned y; /* current row */ + + for (band = first_band (frame->color); + band <= last_band (frame->color); band++) + { + src = dst = frame->pixels [band]; + for (y = orig_height; y; y--) + { + memmove (dst, src, orig_width * sizeof (word_t)); + dst += orig_width; + src += width; + } + if (format == FORMAT_4_2_0 && band == Y) + { + orig_width >>= 1; + orig_height >>= 1; + width >>= 1; + } + } } } if (dec_timer) @@ -544,10 +545,10 @@ decode_state (unsigned state, unsigned level, wfa_t *wfa) * Decode 'state' image of 'wfa' at given 'level'. * * Return value. - * pointer to decoded state image + * pointer to decoded state image * * Side effects: - * 'wfa' states > 'state' are removed. + * 'wfa' states > 'state' are removed. */ { word_t *domains [2]; @@ -571,15 +572,15 @@ decode_state (unsigned state, unsigned level, wfa_t *wfa) */ { word_t *src, *dst; - unsigned y; - + unsigned y; + src = domains [0]; dst = img->pixels [GRAY]; for (y = img->height; y; y--) { - memcpy (dst, src, width_of_level (level) * sizeof (word_t)); - src += width_of_level (level); - dst += img->width; + memcpy (dst, src, width_of_level (level) * sizeof (word_t)); + src += width_of_level (level); + dst += img->width; } Free (domains [0]); } @@ -589,87 +590,87 @@ decode_state (unsigned state, unsigned level, wfa_t *wfa) word_t * decode_range (unsigned range_state, unsigned range_label, unsigned range_level, - word_t **domain, wfa_t *wfa) + word_t **domain, wfa_t *wfa) /* * Compute 'wfa' image of range (identified by 'state' and 'label') * at 'range_level (works as function decode_image()). * * Return value: - * pointer to the pixels in SHORT format + * pointer to the pixels in SHORT format * * Side effects: - * if 'domain' != NULL then also the domain blocks - * of the corresponding range blocks are generated + * if 'domain' != NULL then also the domain blocks + * of the corresponding range blocks are generated * and returned in domain[] - * 'wfa->level_of_state []' is changed + * 'wfa->level_of_state []' is changed */ { - unsigned root_state [3]; /* dummy (for alloc_state_images) */ - image_t *state_image; /* regenerated state image */ - word_t **images; /* pointer to array of pointers - to state images */ - u_word_t *offsets; /* pointer to array of state image - offsets */ + unsigned root_state [3]; /* dummy (for alloc_state_images) */ + image_t *state_image; /* regenerated state image */ + word_t **images; /* pointer to array of pointers + to state images */ + u_word_t *offsets; /* pointer to array of state image + offsets */ word_t *range; enlarge_image (range_level - (wfa->level_of_state [range_state] - 1), - FORMAT_4_4_4, -1, wfa); + FORMAT_4_4_4, -1, wfa); root_state [0] = range_state; state_image = alloc_image (width_of_level (range_level + 1), - height_of_level (range_level + 1), - NO, FORMAT_4_4_4); + height_of_level (range_level + 1), + NO, FORMAT_4_4_4); alloc_state_images (&images, &offsets, state_image, NULL, range_state, - range_level + 1, NO, wfa); + range_level + 1, NO, wfa); compute_state_images (range_level + 1, images, offsets, wfa); range = Calloc (size_of_level (range_level), sizeof (word_t)); - if ((range_level & 1) == 0) /* square image */ + if ((range_level & 1) == 0) /* square image */ { memcpy (range, - images [range_state + (range_level + 1) * wfa->states] - + range_label * size_of_level (range_level), - size_of_level (range_level) * sizeof (word_t)); + images [range_state + (range_level + 1) * wfa->states] + + range_label * size_of_level (range_level), + size_of_level (range_level) * sizeof (word_t)); } - else /* rectangle */ + else /* rectangle */ { word_t *src, *dst; unsigned y; src = images [range_state + (range_level + 1) * wfa->states] - + range_label * width_of_level (range_level); + + range_label * width_of_level (range_level); dst = range; for (y = height_of_level (range_level); y; y--) { - memcpy (dst, src, width_of_level (range_level) * sizeof (word_t)); - dst += width_of_level (range_level); - src += width_of_level (range_level + 1); + memcpy (dst, src, width_of_level (range_level) * sizeof (word_t)); + dst += width_of_level (range_level); + src += width_of_level (range_level + 1); } } - if (domain != NULL) /* copy domain images */ + if (domain != NULL) /* copy domain images */ { - int s; /* domain state */ - unsigned edge; /* counter */ - + int s; /* domain state */ + unsigned edge; /* counter */ + if (ischild (s = wfa->tree [range_state][range_label])) - *domain++ = duplicate_state_image (images [s + (range_level) - * wfa->states], - offsets [s + (range_level) - * wfa->states], - range_level); + *domain++ = duplicate_state_image (images [s + (range_level) + * wfa->states], + offsets [s + (range_level) + * wfa->states], + range_level); for (edge = 0; isedge (s = wfa->into[range_state][range_label][edge]); - edge++) - *domain++ = duplicate_state_image (images [s + (range_level) - * wfa->states], - offsets [s + (range_level) - * wfa->states], - range_level); + edge++) + *domain++ = duplicate_state_image (images [s + (range_level) + * wfa->states], + offsets [s + (range_level) + * wfa->states], + range_level); *domain = NULL; } free_state_images (range_level + 1, NO, images, offsets, NULL, range_state, - NO, wfa); + NO, wfa); free_image (state_image); return range; @@ -684,102 +685,102 @@ smooth_image (unsigned sf, const wfa_t *wfa, image_t *image) * No return value. * * Side effects: - * pixel values of the 'image' are modified with respect to 's' + * pixel values of the 'image' are modified with respect to 's' */ { - int is, inegs; /* integer factors of s and 1 - s*/ - unsigned state; + int is, inegs; /* integer factors of s and 1 - s*/ + unsigned state; unsigned img_width = image->width; unsigned img_height = image->height; - real_t s = 1.0 - sf / 200.0; + real_t s = 1.0 - sf / 200.0; - if (s < 0.5 || s >= 1) /* value out of range */ + if (s < 0.5 || s >= 1) /* value out of range */ return; - is = s * 512 + .5; /* integer representation of s */ - inegs = (1 - s) * 512 + .5; /* integer representation of 1 - s */ + is = s * 512 + .5; /* integer representation of s */ + inegs = (1 - s) * 512 + .5; /* integer representation of 1 - s */ for (state = wfa->basis_states; - state < (wfa->wfainfo->color - ? wfa->tree [wfa->root_state][0] - : wfa->states); state++) + state < (wfa->wfainfo->color + ? wfa->tree [wfa->root_state][0] + : wfa->states); state++) { word_t *bptr = image->pixels [Y]; /* pointer to right or - lower line */ + lower line */ unsigned level = wfa->level_of_state[state]; /* level of state image */ unsigned width = width_of_level (level); /* size of state image */ unsigned height = height_of_level (level); /* size of state image */ if (wfa->y [state][1] >= img_height || wfa->x [state][1] >= img_width) - continue; /* outside visible area */ - - if (level % 2) /* horizontal smoothing */ + continue; /* outside visible area */ + + if (level % 2) /* horizontal smoothing */ { - unsigned i; /* line counter */ - word_t *img1; /* pointer to left or upper line */ - word_t *img2; /* pointer to right or lower line */ - - img1 = bptr + (wfa->y [state][1] - 1) * img_width - + wfa->x [state][1]; - img2 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1]; - - for (i = min (width, img_width - wfa->x [state][1]); i; - i--, img1++, img2++) - { - int tmp = *img1; - + unsigned i; /* line counter */ + word_t *img1; /* pointer to left or upper line */ + word_t *img2; /* pointer to right or lower line */ + + img1 = bptr + (wfa->y [state][1] - 1) * img_width + + wfa->x [state][1]; + img2 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1]; + + for (i = min (width, img_width - wfa->x [state][1]); i; + i--, img1++, img2++) + { + int tmp = *img1; + #ifdef HAVE_SIGNED_SHIFT - *img1 = (((is * tmp) >> 10) << 1) - + (((inegs * (int) *img2) >> 10) << 1); - *img2 = (((is * (int) *img2) >> 10) << 1) - + (((inegs * tmp) >> 10) << 1); + *img1 = (((is * tmp) >> 10) << 1) + + (((inegs * (int) *img2) >> 10) << 1); + *img2 = (((is * (int) *img2) >> 10) << 1) + + (((inegs * tmp) >> 10) << 1); #else /* not HAVE_SIGNED_SHIFT */ - *img1 = (((is * tmp) / 1024) * 2) - + (((inegs * (int) *img2) / 1024) * 2); - *img2 = (((is * (int) *img2) / 1024) * 2) - + (((inegs * tmp) / 1024) *2); + *img1 = (((is * tmp) / 1024) * 2) + + (((inegs * (int) *img2) / 1024) * 2); + *img2 = (((is * (int) *img2) / 1024) * 2) + + (((inegs * tmp) / 1024) *2); #endif /* not HAVE_SIGNED_SHIFT */ - } + } } - else /* vertical smoothing */ + else /* vertical smoothing */ { - unsigned i; /* line counter */ - word_t *img1; /* pointer to left or upper line */ - word_t *img2; /* pointer to right or lower line */ - - img1 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1] - 1; - img2 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1]; - - for (i = min (height, img_height - wfa->y [state][1]); i; - i--, img1 += img_width, img2 += img_width) - { - int tmp = *img1; - + unsigned i; /* line counter */ + word_t *img1; /* pointer to left or upper line */ + word_t *img2; /* pointer to right or lower line */ + + img1 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1] - 1; + img2 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1]; + + for (i = min (height, img_height - wfa->y [state][1]); i; + i--, img1 += img_width, img2 += img_width) + { + int tmp = *img1; + #ifdef HAVE_SIGNED_SHIFT - *img1 = (((is * tmp) >> 10) << 1) - + (((inegs * (int) *img2) >> 10) << 1); - *img2 = (((is * (int) *img2) >> 10) << 1) - + (((inegs * tmp) >> 10) << 1); + *img1 = (((is * tmp) >> 10) << 1) + + (((inegs * (int) *img2) >> 10) << 1); + *img2 = (((is * (int) *img2) >> 10) << 1) + + (((inegs * tmp) >> 10) << 1); #else /* not HAVE_SIGNED_SHIFT */ - *img1 = (((is * tmp) / 1024) * 2) - + (((inegs * (int) *img2) / 1024) * 2); - *img2 = (((is * (int) *img2) / 1024) * 2) - + (((inegs * tmp) / 1024) *2); + *img1 = (((is * tmp) / 1024) * 2) + + (((inegs * (int) *img2) / 1024) * 2); + *img2 = (((is * (int) *img2) / 1024) * 2) + + (((inegs * tmp) / 1024) *2); #endif /* not HAVE_SIGNED_SHIFT */ - } + } } } } /***************************************************************************** - private code + private code *****************************************************************************/ static void enlarge_image (int enlarge_factor, format_e format, unsigned y_root, - wfa_t *wfa) + wfa_t *wfa) /* * Enlarge or reduce size of state images by factor 2^'enlarge_factor'. * Use 4:2:0 subsampling if specified by 'format', else use 4:4:4 format. @@ -788,8 +789,8 @@ enlarge_image (int enlarge_factor, format_e format, unsigned y_root, * No return value. * * Side effects: - * coordinates of ranges and motion blocks in the WFA structure 'wfa' - * are modified. + * coordinates of ranges and motion blocks in the WFA structure 'wfa' + * are modified. */ { @@ -799,53 +800,53 @@ enlarge_image (int enlarge_factor, format_e format, unsigned y_root, if (enlarge_factor == 0) { - state = y_root + 1; - enlarge_factor = -1; + state = y_root + 1; + enlarge_factor = -1; } else - state = wfa->basis_states; + state = wfa->basis_states; for (; state < wfa->states; state++) { - unsigned label, n; - - wfa->level_of_state [state] - = max (wfa->level_of_state [state] + enlarge_factor * 2, 0); - - for (label = 0; label < MAXLABELS; label++) - if (enlarge_factor > 0) - { - wfa->x [state][label] <<= enlarge_factor; - wfa->y [state][label] <<= enlarge_factor; - for (n = enlarge_factor; n; n--) - { - wfa->mv_tree [state][label].fx *= 2; - wfa->mv_tree [state][label].fy *= 2; - wfa->mv_tree [state][label].bx *= 2; - wfa->mv_tree [state][label].by *= 2; - } - } - else /* enlarge_factor < 0 */ - { - wfa->x [state][label] >>= - enlarge_factor; - wfa->y [state][label] >>= - enlarge_factor; - for (n = - enlarge_factor; n; n--) - { - wfa->mv_tree [state][label].fx /= 2; - wfa->mv_tree [state][label].fy /= 2; - wfa->mv_tree [state][label].bx /= 2; - wfa->mv_tree [state][label].by /= 2; - } - } - if (format == FORMAT_4_2_0 && state == y_root) - enlarge_factor--; + unsigned label, n; + + wfa->level_of_state [state] + = max (wfa->level_of_state [state] + enlarge_factor * 2, 0); + + for (label = 0; label < MAXLABELS; label++) + if (enlarge_factor > 0) + { + wfa->x [state][label] <<= enlarge_factor; + wfa->y [state][label] <<= enlarge_factor; + for (n = enlarge_factor; n; n--) + { + wfa->mv_tree [state][label].fx *= 2; + wfa->mv_tree [state][label].fy *= 2; + wfa->mv_tree [state][label].bx *= 2; + wfa->mv_tree [state][label].by *= 2; + } + } + else /* enlarge_factor < 0 */ + { + wfa->x [state][label] >>= - enlarge_factor; + wfa->y [state][label] >>= - enlarge_factor; + for (n = - enlarge_factor; n; n--) + { + wfa->mv_tree [state][label].fx /= 2; + wfa->mv_tree [state][label].fy /= 2; + wfa->mv_tree [state][label].bx /= 2; + wfa->mv_tree [state][label].by /= 2; + } + } + if (format == FORMAT_4_2_0 && state == y_root) + enlarge_factor--; } } } static void compute_actual_size (unsigned luminance_root, - unsigned *width, unsigned *height, const wfa_t *wfa) + unsigned *width, unsigned *height, const wfa_t *wfa) /* * Compute actual size of the frame represented by the given 'wfa'. * (The reconstructed frame may get larger than the original due @@ -853,24 +854,24 @@ compute_actual_size (unsigned luminance_root, * If 'luminance_root' < MAXSTATES then the size of chroma ranges (4:2:0). * * Return values: - * actual 'width' and 'height' of the decoded frame. + * actual 'width' and 'height' of the decoded frame. */ { - unsigned x = 0, y = 0; /* maximum coordinates */ - unsigned state; /* counter */ + unsigned x = 0, y = 0; /* maximum coordinates */ + unsigned state; /* counter */ for (state = wfa->basis_states; state < wfa->states; state++) if (isedge (wfa->into [state][0][0]) || isedge (wfa->into [state][1][0])) { - unsigned mult = state > luminance_root ? 2 : 1; - - x = max ((wfa->x [state][0] - + width_of_level (wfa->level_of_state [state])) * mult, x); - y = max ((wfa->y [state][0] - + height_of_level (wfa->level_of_state [state])) * mult, y); + unsigned mult = state > luminance_root ? 2 : 1; + + x = max ((wfa->x [state][0] + + width_of_level (wfa->level_of_state [state])) * mult, x); + y = max ((wfa->y [state][0] + + height_of_level (wfa->level_of_state [state])) * mult, y); } - if (x & 1) /* ensure that image size is even */ + if (x & 1) /* ensure that image size is even */ x++; if (y & 1) y++; @@ -880,8 +881,8 @@ compute_actual_size (unsigned luminance_root, static void alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, - const unsigned *root_state, unsigned range_state, - unsigned max_level, format_e format, const wfa_t *wfa) + const unsigned *root_state, unsigned range_state, + unsigned max_level, format_e format, const wfa_t *wfa) /* * Generate list of 'wfa' state images which have to be computed for * each level to obtain the decoded 'frame'. 'root_state[]' denotes the @@ -893,24 +894,24 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, * image of 'wfa->root_state'. * * Return values: - * '*images' Pointer to array of state image pointers - * '*offsets' Pointer to array of state image offsets. + * '*images' Pointer to array of state image pointers + * '*offsets' Pointer to array of state image offsets. * * Side effects: - * The arrays given above are filled with useful values. + * The arrays given above are filled with useful values. */ { - word_t **simg; /* ptr to list of state image ptr's */ - u_word_t *offs; /* ptr to list of offsets */ - unsigned level; /* counter */ + word_t **simg; /* ptr to list of state image ptr's */ + u_word_t *offs; /* ptr to list of offsets */ + unsigned level; /* counter */ - simg = Calloc (wfa->states * (max_level + 1), sizeof (word_t *)); - offs = Calloc (wfa->states * (max_level + 1), sizeof (u_word_t)); + simg = Calloc (wfa->states * (max_level + 1), sizeof (word_t *)); + offs = Calloc (wfa->states * (max_level + 1), sizeof (u_word_t)); /* * Initialize buffers for those state images which are at 'max_level'. */ - if (range_state > 0) /* a range is given */ + if (range_state > 0) /* a range is given */ { simg [range_state + max_level * wfa->states] = frame->pixels [GRAY]; offs [range_state + max_level * wfa->states] = frame->width; @@ -920,25 +921,25 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, unsigned state; for (state = wfa->basis_states; state <= root_state [Y]; state++) - if (wfa->level_of_state [state] == max_level) - { - simg [state + max_level * wfa->states] - = (frame->pixels [Y] + wfa->y [state][0] * frame->width - + wfa->x [state][0]); - offs [state + max_level * wfa->states] = frame->width; - } + if (wfa->level_of_state [state] == max_level) + { + simg [state + max_level * wfa->states] + = (frame->pixels [Y] + wfa->y [state][0] * frame->width + + wfa->x [state][0]); + offs [state + max_level * wfa->states] = frame->width; + } if (frame->color) { - unsigned width = format == FORMAT_4_2_0 ? - (frame->width >> 1) : frame->width; - for (; state < wfa->states; state++) - if (wfa->level_of_state [state] == max_level) - { - simg [state + max_level * wfa->states] - = (frame->pixels [state > root_state [Cb] ? Cr : Cb] - + wfa->y [state][0] * width + wfa->x [state][0]); - offs [state + max_level * wfa->states] = width; - } + unsigned width = format == FORMAT_4_2_0 ? + (frame->width >> 1) : frame->width; + for (; state < wfa->states; state++) + if (wfa->level_of_state [state] == max_level) + { + simg [state + max_level * wfa->states] + = (frame->pixels [state > root_state [Cb] ? Cr : Cb] + + wfa->y [state][0] * width + wfa->x [state][0]); + offs [state + max_level * wfa->states] = width; + } } } @@ -954,63 +955,63 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, * Range approximation with child. */ for (state = 1; state < (range_state > 0 ? - range_state + 1 : wfa->states); state++) - if (simg [state + level * wfa->states]) - for (label = 0; label < MAXLABELS; label++) - if (ischild (child = wfa->tree[state][label])) - { - if (isedge (wfa->into[state][label][0])) - { - /* - * Allocate new image block. - */ - simg [child + (level - 1) * wfa->states] - = Calloc (size_of_level (level - 1), sizeof (word_t)); - offs [child + (level - 1) * wfa->states] - = width_of_level (level - 1); - } - else - { - /* - * Use image block and offset of parent. - */ - if (level & 1) /* split vertically */ - { - simg [child + (level - 1) * wfa->states] - = (simg [state + level * wfa->states] - + label * (height_of_level (level - 1) - * offs [state - + level * wfa->states])); - } - else /* split horizontally */ - { - simg [child + (level - 1) * wfa->states] - = (simg [state + level * wfa->states] - + label * width_of_level (level - 1)); - } - offs [child + (level - 1) * wfa->states] - = offs [state + level * wfa->states]; - } - } + range_state + 1 : wfa->states); state++) + if (simg [state + level * wfa->states]) + for (label = 0; label < MAXLABELS; label++) + if (ischild (child = wfa->tree[state][label])) + { + if (isedge (wfa->into[state][label][0])) + { + /* + * Allocate new image block. + */ + simg [child + (level - 1) * wfa->states] + = Calloc (size_of_level (level - 1), sizeof (word_t)); + offs [child + (level - 1) * wfa->states] + = width_of_level (level - 1); + } + else + { + /* + * Use image block and offset of parent. + */ + if (level & 1) /* split vertically */ + { + simg [child + (level - 1) * wfa->states] + = (simg [state + level * wfa->states] + + label * (height_of_level (level - 1) + * offs [state + + level * wfa->states])); + } + else /* split horizontally */ + { + simg [child + (level - 1) * wfa->states] + = (simg [state + level * wfa->states] + + label * width_of_level (level - 1)); + } + offs [child + (level - 1) * wfa->states] + = offs [state + level * wfa->states]; + } + } /* * Range approximation with linear combination */ for (state = 1; state < (range_state > 0 ? - range_state + 1 : wfa->states); state++) - if (simg [state + level * wfa->states]) - for (label = 0; label < MAXLABELS; label++) - for (edge = 0; isedge (domain = wfa->into[state][label][edge]); - edge++) - { - if (domain > 0 /* don't allocate memory for state 0 */ - && !simg [domain + (level - 1) * wfa->states]) - { - simg [domain + (level - 1) * wfa->states] - = Calloc (size_of_level (level - 1), sizeof (word_t)); - offs [domain + (level - 1) * wfa->states] - = width_of_level (level - 1); - } - } + range_state + 1 : wfa->states); state++) + if (simg [state + level * wfa->states]) + for (label = 0; label < MAXLABELS; label++) + for (edge = 0; isedge (domain = wfa->into[state][label][edge]); + edge++) + { + if (domain > 0 /* don't allocate memory for state 0 */ + && !simg [domain + (level - 1) * wfa->states]) + { + simg [domain + (level - 1) * wfa->states] + = Calloc (size_of_level (level - 1), sizeof (word_t)); + offs [domain + (level - 1) * wfa->states] + = width_of_level (level - 1); + } + } } @@ -1020,8 +1021,8 @@ alloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, static void free_state_images (unsigned max_level, bool_t color, word_t **state_image, - u_word_t *offset, const unsigned *root_state, - unsigned range_state, format_e format, const wfa_t *wfa) + u_word_t *offset, const unsigned *root_state, + unsigned range_state, format_e format, const wfa_t *wfa) /* * Free memory of state images. * For more details refer to the inverse function 'alloc_state_images()'. @@ -1029,10 +1030,10 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image, * No return value. * * Side effects: - * arrays 'state_image' and 'offset' are discarded. + * arrays 'state_image' and 'offset' are discarded. */ { - word_t marker; /* ptr is required as a marker */ + word_t marker; /* ptr is required as a marker */ unsigned level; if (range_state > 0) @@ -1047,19 +1048,19 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image, * Initialize state image array with states at 'max_level' */ for (state = wfa->basis_states; state <= root_state [Y]; state++) - if (wfa->level_of_state [state] == max_level) - state_image [state + max_level * wfa->states] = ▮ + if (wfa->level_of_state [state] == max_level) + state_image [state + max_level * wfa->states] = ▮ if (color) { - if (format == FORMAT_4_2_0) - level = max_level - 2; - else - level = max_level; + if (format == FORMAT_4_2_0) + level = max_level - 2; + else + level = max_level; - for (; state < wfa->states; state++) - if (wfa->level_of_state [state] == level) - state_image [state + level * wfa->states] = ▮ + for (; state < wfa->states; state++) + if (wfa->level_of_state [state] == level) + state_image [state + level * wfa->states] = ▮ } } @@ -1071,37 +1072,37 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image, * Range approximation with child. */ for (state = 1; state < (range_state > 0 ? - range_state + 1 : wfa->states); state++) - if (state_image [state + level * wfa->states]) - for (label = 0; label < MAXLABELS; label++) - if (ischild (child = wfa->tree[state][label])) - { - if (isedge (wfa->into[state][label][0]) - && (state_image [child + (level - 1) * wfa->states] - != &marker)) - Free (state_image [child + (level - 1) * wfa->states]); - state_image [child + (level - 1) * wfa->states] = ▮ - } + range_state + 1 : wfa->states); state++) + if (state_image [state + level * wfa->states]) + for (label = 0; label < MAXLABELS; label++) + if (ischild (child = wfa->tree[state][label])) + { + if (isedge (wfa->into[state][label][0]) + && (state_image [child + (level - 1) * wfa->states] + != &marker)) + Free (state_image [child + (level - 1) * wfa->states]); + state_image [child + (level - 1) * wfa->states] = ▮ + } /* * Range approximation with linear combination */ for (state = 1; state < (range_state > 0 ? - range_state + 1 : wfa->states); - state++) - if (state_image [state + level * wfa->states]) - for (label = 0; label < MAXLABELS; label++) - for (edge = 0; isedge (domain = wfa->into[state][label][edge]); - edge++) - if (domain > 0 - && (state_image [domain + (level - 1) * wfa->states] - != NULL) - && (state_image [domain + (level - 1) * wfa->states] - != &marker)) - { - Free (state_image [domain + (level - 1) * wfa->states]); - state_image [domain + (level - 1) * wfa->states] - = ▮ - } + range_state + 1 : wfa->states); + state++) + if (state_image [state + level * wfa->states]) + for (label = 0; label < MAXLABELS; label++) + for (edge = 0; isedge (domain = wfa->into[state][label][edge]); + edge++) + if (domain > 0 + && (state_image [domain + (level - 1) * wfa->states] + != NULL) + && (state_image [domain + (level - 1) * wfa->states] + != &marker)) + { + Free (state_image [domain + (level - 1) * wfa->states]); + state_image [domain + (level - 1) * wfa->states] + = ▮ + } } Free (state_image); Free (offset); @@ -1109,7 +1110,7 @@ free_state_images (unsigned max_level, bool_t color, word_t **state_image, static void compute_state_images (unsigned max_level, word_t **simg, - const u_word_t *offset, const wfa_t *wfa) + const u_word_t *offset, const wfa_t *wfa) /* * Compute all state images of the 'wfa' at level {1, ... , 'max_level'} * which are marked in the array 'simg' (offsets of state images @@ -1121,8 +1122,8 @@ compute_state_images (unsigned max_level, word_t **simg, * No return value. * * Side effects: - * state images (given by pointers in the array 'state_image') - * are computed. + * state images (given by pointers in the array 'state_image') + * are computed. */ { unsigned level, state; @@ -1132,8 +1133,8 @@ compute_state_images (unsigned max_level, word_t **simg, */ for (state = 1; state < wfa->states; state++) - if (simg [state] != NULL) /* compute image at level 0 */ - *simg [state] = (int) (wfa->final_distribution[state] * 8 + .5) * 2; + if (simg [state] != NULL) /* compute image at level 0 */ + *simg [state] = (int) (wfa->final_distribution[state] * 8 + .5) * 2; /* * Compute images of states @@ -1153,351 +1154,351 @@ compute_state_images (unsigned max_level, word_t **simg, unsigned height = height_of_level (level - 1); for (state = 1; state < wfa->states; state++) - if (simg [state + level * wfa->states] != NULL) - for (label = 0; label < MAXLABELS; label++) - if (isedge (wfa->into [state][label][0])) - { - unsigned edge; - int domain; - word_t *range; /* address of current range */ - bool_t prediction_used; /* ND prediction found ? */ - - /* - * Compute address of range image - */ - if (level & 1) /* split vertically */ - { - range = simg [state + level * wfa->states] - + label * (height_of_level (level - 1) - * offset [state - + level * wfa->states]); - } - else /* split horizontally */ - { - range = simg [state + level * wfa->states] - + label * width_of_level (level - 1); - } - - /* - * Generate the state images by adding the corresponding - * weighted state images: - * subimage [label] = - * weight_1 * image_1 + ... + weight_n * image_n - */ - if (!ischild (domain = wfa->tree[state][label])) - prediction_used = NO; - else - { - unsigned y; - word_t *src; - word_t *dst; - unsigned src_offset; - unsigned dst_offset; - - prediction_used = YES; - /* - * Copy child image - */ - src = simg [domain + (level - 1) * wfa->states]; - src_offset = offset [domain + (level - 1) * wfa->states] ; - dst = range; - dst_offset = offset [state + level * wfa->states]; - for (y = height; y; y--) - { - memcpy (dst, src, width * sizeof (word_t)); - src += src_offset; - dst += dst_offset; - } - } - - if (!prediction_used - && isedge (domain = wfa->into[state][label][0])) - { - /* - * If prediction is not used then the range is - * filled with the first domain. No addition is needed. - */ - edge = 0; - if (domain != 0) - { - int weight; - word_t *src; - unsigned src_offset; - - src = simg [domain + ((level - 1) - * wfa->states)]; - src_offset = offset [domain + ((level - 1) - * wfa->states)] - width; - weight = wfa->int_weight [state][label][edge]; - - if (width == 1) /* can't add two-pixels in a row */ - { - word_t *dst; - unsigned dst_offset; - - dst = range; - dst_offset = offset [state + level * wfa->states] - - width; + if (simg [state + level * wfa->states] != NULL) + for (label = 0; label < MAXLABELS; label++) + if (isedge (wfa->into [state][label][0])) + { + unsigned edge; + int domain; + word_t *range; /* address of current range */ + bool_t prediction_used; /* ND prediction found ? */ + + /* + * Compute address of range image + */ + if (level & 1) /* split vertically */ + { + range = simg [state + level * wfa->states] + + label * (height_of_level (level - 1) + * offset [state + + level * wfa->states]); + } + else /* split horizontally */ + { + range = simg [state + level * wfa->states] + + label * width_of_level (level - 1); + } + + /* + * Generate the state images by adding the corresponding + * weighted state images: + * subimage [label] = + * weight_1 * image_1 + ... + weight_n * image_n + */ + if (!ischild (domain = wfa->tree[state][label])) + prediction_used = NO; + else + { + unsigned y; + word_t *src; + word_t *dst; + unsigned src_offset; + unsigned dst_offset; + + prediction_used = YES; + /* + * Copy child image + */ + src = simg [domain + (level - 1) * wfa->states]; + src_offset = offset [domain + (level - 1) * wfa->states] ; + dst = range; + dst_offset = offset [state + level * wfa->states]; + for (y = height; y; y--) + { + memcpy (dst, src, width * sizeof (word_t)); + src += src_offset; + dst += dst_offset; + } + } + + if (!prediction_used + && isedge (domain = wfa->into[state][label][0])) + { + /* + * If prediction is not used then the range is + * filled with the first domain. No addition is needed. + */ + edge = 0; + if (domain != 0) + { + int weight; + word_t *src; + unsigned src_offset; + + src = simg [domain + ((level - 1) + * wfa->states)]; + src_offset = offset [domain + ((level - 1) + * wfa->states)] - width; + weight = wfa->int_weight [state][label][edge]; + + if (width == 1) /* can't add two-pixels in a row */ + { + word_t *dst; + unsigned dst_offset; + + dst = range; + dst_offset = offset [state + level * wfa->states] + - width; #ifdef HAVE_SIGNED_SHIFT - *dst++ = ((weight * (int) *src++) >> 10) << 1; -#else /* not HAVE_SIGNED_SHIFT */ - *dst++ = ((weight * (int) *src++) / 1024) * 2; + *dst++ = ((weight * (int) *src++) >> 10) << 1; +#else /* not HAVE_SIGNED_SHIFT */ + *dst++ = ((weight * (int) *src++) / 1024) * 2; #endif /* not HAVE_SIGNED_SHIFT */ - if (height == 2) - { - src += src_offset; - dst += dst_offset; + if (height == 2) + { + src += src_offset; + dst += dst_offset; #ifdef HAVE_SIGNED_SHIFT - *dst++ = ((weight * (int) *src++) >> 10) << 1; + *dst++ = ((weight * (int) *src++) >> 10) << 1; #else /* not HAVE_SIGNED_SHIFT */ - *dst++ = ((weight * (int) *src++) / 1024) * 2; + *dst++ = ((weight * (int) *src++) / 1024) * 2; #endif /* not HAVE_SIGNED_SHIFT */ - } - } - else - { - unsigned y; - int *idst; - unsigned idst_offset; - - idst = (int *) range; - idst_offset = (offset [state + level * wfa->states] - - width) / 2; - for (y = height; y; y--) - { - int *comp_dst = idst + (width >> 1); - - for (; idst != comp_dst; ) - { - int tmp; /* temp. value of adjacent pixels */ + } + } + else + { + unsigned y; + int *idst; + unsigned idst_offset; + + idst = (int *) range; + idst_offset = (offset [state + level * wfa->states] + - width) / 2; + for (y = height; y; y--) + { + int *comp_dst = idst + (width >> 1); + + for (; idst != comp_dst; ) + { + int tmp; /* temp. value of adjacent pixels */ #ifdef HAVE_SIGNED_SHIFT -# if BYTE_ORDER == LITTLE_ENDIAN - tmp = (((weight * (int) src [1]) >> 10) << 17) - | (((weight * (int) src [0]) >> 9) - & 0xfffe); -# else - tmp = (((weight * (int) src [0]) >> 10) << 17) - | (((weight * (int) src [1]) >> 9) - & 0xfffe); -# endif +# if BYTE_ORDER == LITTLE_ENDIAN + tmp = (((weight * (int) src [1]) >> 10) << 17) + | (((weight * (int) src [0]) >> 9) + & 0xfffe); +# else + tmp = (((weight * (int) src [0]) >> 10) << 17) + | (((weight * (int) src [1]) >> 9) + & 0xfffe); +# endif #else /* not HAVE_SIGNED_SHIFT */ -# if BYTE_ORDER == LITTLE_ENDIAN - tmp = (((weight * (int) src [1]) / 1024) - * 131072) - | (((weight * (int) src [0])/ 512) - & 0xfffe); -# else - tmp = (((weight * (int) src [0]) / 1024) - * 131072) - | (((weight * (int) src [1]) / 512) - & 0xfffe); -# endif /* not WORDS_BIGENDIAN */ -#endif - src += 2; - *idst++ = tmp & 0xfffefffe; - } - src += src_offset; - idst += idst_offset; - } - } - } - else - { - int weight = (int) (wfa->weight[state][label][edge] - * wfa->final_distribution[0] - * 8 + .5) * 2; - /* - * Range needs domain 0 - * (the constant function f(x, y) = 1), - * hence a faster algorithm is used. - */ - if (width == 1) /* can't add two-pixels in a row */ - { - word_t *dst; - unsigned dst_offset; - - dst = range; - dst_offset = offset [state + level * wfa->states] - - width; - - *dst++ = weight; - if (height == 2) - { - dst += dst_offset; - *dst++ = weight; - } - } - else - { - unsigned x, y; - int *idst; - unsigned idst_offset; - - weight = (weight * 65536) | (weight & 0xffff); - idst = (int *) range; - idst_offset = offset [state + level * wfa->states] - / 2; - for (x = width >> 1; x; x--) - *idst++ = weight & 0xfffefffe; - idst += (offset [state + level * wfa->states] - - width) / 2; - - for (y = height - 1; y; y--) - { - memcpy (idst, idst - idst_offset, - width * sizeof (word_t)); - idst += idst_offset; - } - } - } - edge = 1; - } - else - edge = 0; - - /* - * Add remaining weighted domain images to current range - */ - for (; isedge (domain = wfa->into[state][label][edge]); - edge++) - { - if (domain != 0) - { - word_t *src; - unsigned src_offset; - int weight; - - src = simg [domain + (level - 1) * wfa->states]; - src_offset = offset [domain + ((level - 1) - * wfa->states)] - width; - weight = wfa->int_weight [state][label][edge]; - - if (width == 1) /* can't add two-pixels in a row */ - { - word_t *dst; - unsigned dst_offset; - - dst = range; - dst_offset = offset [state + level * wfa->states] - - width; +# if BYTE_ORDER == LITTLE_ENDIAN + tmp = (((weight * (int) src [1]) / 1024) + * 131072) + | (((weight * (int) src [0])/ 512) + & 0xfffe); +# else + tmp = (((weight * (int) src [0]) / 1024) + * 131072) + | (((weight * (int) src [1]) / 512) + & 0xfffe); +# endif +#endif /* not HAVE_SIGNED_SHIFT */ + src += 2; + *idst++ = tmp & 0xfffefffe; + } + src += src_offset; + idst += idst_offset; + } + } + } + else + { + int weight = (int) (wfa->weight[state][label][edge] + * wfa->final_distribution[0] + * 8 + .5) * 2; + /* + * Range needs domain 0 + * (the constant function f(x, y) = 1), + * hence a faster algorithm is used. + */ + if (width == 1) /* can't add two-pixels in a row */ + { + word_t *dst; + unsigned dst_offset; + + dst = range; + dst_offset = offset [state + level * wfa->states] + - width; + + *dst++ = weight; + if (height == 2) + { + dst += dst_offset; + *dst++ = weight; + } + } + else + { + unsigned x, y; + int *idst; + unsigned idst_offset; + + weight = (weight * 65536) | (weight & 0xffff); + idst = (int *) range; + idst_offset = offset [state + level * wfa->states] + / 2; + for (x = width >> 1; x; x--) + *idst++ = weight & 0xfffefffe; + idst += (offset [state + level * wfa->states] + - width) / 2; + + for (y = height - 1; y; y--) + { + memcpy (idst, idst - idst_offset, + width * sizeof (word_t)); + idst += idst_offset; + } + } + } + edge = 1; + } + else + edge = 0; + + /* + * Add remaining weighted domain images to current range + */ + for (; isedge (domain = wfa->into[state][label][edge]); + edge++) + { + if (domain != 0) + { + word_t *src; + unsigned src_offset; + int weight; + + src = simg [domain + (level - 1) * wfa->states]; + src_offset = offset [domain + ((level - 1) + * wfa->states)] - width; + weight = wfa->int_weight [state][label][edge]; + + if (width == 1) /* can't add two-pixels in a row */ + { + word_t *dst; + unsigned dst_offset; + + dst = range; + dst_offset = offset [state + level * wfa->states] + - width; #ifdef HAVE_SIGNED_SHIFT - *dst++ += ((weight * (int) *src++) >> 10) << 1; + *dst++ += ((weight * (int) *src++) >> 10) << 1; #else /* not HAVE_SIGNED_SHIFT */ - *dst++ += ((weight * (int) *src++) / 1024) * 2; + *dst++ += ((weight * (int) *src++) / 1024) * 2; #endif /* not HAVE_SIGNED_SHIFT */ - if (height == 2) - { - src += src_offset; - dst += dst_offset; + if (height == 2) + { + src += src_offset; + dst += dst_offset; #ifdef HAVE_SIGNED_SHIFT - *dst++ += ((weight * (int) *src++) >> 10) << 1; + *dst++ += ((weight * (int) *src++) >> 10) << 1; #else /* not HAVE_SIGNED_SHIFT */ - *dst++ += ((weight * (int) *src++) / 1024) * 2; + *dst++ += ((weight * (int) *src++) / 1024) * 2; #endif /* not HAVE_SIGNED_SHIFT */ - } - } - else - { - int *idst; - unsigned idst_offset; - unsigned y; - - idst = (int *) range; - idst_offset = (offset [state + level * wfa->states] - - width) / 2; - - for (y = height; y; y--) - { - int *comp_dst = idst + (width >> 1); - - for (; idst != comp_dst;) - { - int tmp; /* temp. value of adjacent pixels */ + } + } + else + { + int *idst; + unsigned idst_offset; + unsigned y; + + idst = (int *) range; + idst_offset = (offset [state + level * wfa->states] + - width) / 2; + + for (y = height; y; y--) + { + int *comp_dst = idst + (width >> 1); + + for (; idst != comp_dst;) + { + int tmp; /* temp. value of adjacent pixels */ #ifdef HAVE_SIGNED_SHIFT -# if BYTE_ORDER == LITTLE_ENDIAN - tmp = (((weight * (int) src [1]) >> 10) << 17) - | (((weight * (int) src [0]) >> 9) - & 0xfffe); -# else - tmp = (((weight * (int)src [0]) >> 10) << 17) - | (((weight * (int)src [1]) >> 9) - & 0xfffe); -# endif +# if BYTE_ORDER == LITTLE_ENDIAN + tmp = (((weight * (int) src [1]) >> 10) << 17) + | (((weight * (int) src [0]) >> 9) + & 0xfffe); +# else + tmp = (((weight * (int)src [0]) >> 10) << 17) + | (((weight * (int)src [1]) >> 9) + & 0xfffe); +# endif #else /* not HAVE_SIGNED_SHIFT */ -# if BYTE_ORDER == LITTLE_ENDIAN - tmp = (((weight * (int) src [1]) / 1024) - * 131072) - | (((weight * (int) src [0])/ 512) - & 0xfffe); -# else - tmp = (((weight * (int) src [0]) / 1024) - * 131072) - | (((weight * (int) src [1])/ 512) - & 0xfffe); -# endif /* not WORDS_BIGENDIAN */ -#endif - src += 2; - *idst = (*idst + tmp) & 0xfffefffe; - idst++; - } - src += src_offset; - idst += idst_offset; - } - } - } - else - { - int weight = (int) (wfa->weight[state][label][edge] - * wfa->final_distribution[0] - * 8 + .5) * 2; - /* - * Range needs domain 0 - * (the constant function f(x, y) = 1), - * hence a faster algorithm is used. - */ - if (width == 1) /* can't add two-pixels in a row */ - { - word_t *dst; - unsigned dst_offset; - - dst = range; - dst_offset = offset [state + level * wfa->states] - - width; - - *dst++ += weight; - if (height == 2) - { - dst += dst_offset; - *dst++ += weight; - } - } - else - { - int *idst; - unsigned idst_offset; - unsigned y; - - weight = (weight * 65536) | (weight & 0xffff); - idst = (int *) range; - idst_offset = (offset [state + level * wfa->states] - - width) /2; - - for (y = height; y; y--) - { - int *comp_dst = idst + (width >> 1); - - for (; idst != comp_dst; ) - { - *idst = (*idst + weight) & 0xfffefffe; +# if BYTE_ORDER == LITTLE_ENDIAN + tmp = (((weight * (int) src [1]) / 1024) + * 131072) + | (((weight * (int) src [0])/ 512) + & 0xfffe); +# else + tmp = (((weight * (int) src [0]) / 1024) + * 131072) + | (((weight * (int) src [1])/ 512) + & 0xfffe); +# endif +#endif /* not HAVE_SIGNED_SHIFT */ + src += 2; + *idst = (*idst + tmp) & 0xfffefffe; + idst++; + } + src += src_offset; + idst += idst_offset; + } + } + } + else + { + int weight = (int) (wfa->weight[state][label][edge] + * wfa->final_distribution[0] + * 8 + .5) * 2; + /* + * Range needs domain 0 + * (the constant function f(x, y) = 1), + * hence a faster algorithm is used. + */ + if (width == 1) /* can't add two-pixels in a row */ + { + word_t *dst; + unsigned dst_offset; + + dst = range; + dst_offset = offset [state + level * wfa->states] + - width; + + *dst++ += weight; + if (height == 2) + { + dst += dst_offset; + *dst++ += weight; + } + } + else + { + int *idst; + unsigned idst_offset; + unsigned y; + + weight = (weight * 65536) | (weight & 0xffff); + idst = (int *) range; + idst_offset = (offset [state + level * wfa->states] + - width) /2; + + for (y = height; y; y--) + { + int *comp_dst = idst + (width >> 1); + + for (; idst != comp_dst; ) + { + *idst = (*idst + weight) & 0xfffefffe; idst++; - } - idst += idst_offset; - } - } - } - } - } + } + idst += idst_offset; + } + } + } + } + } } } @@ -1509,24 +1510,24 @@ duplicate_state_image (const word_t *domain, unsigned offset, unsigned level) * to the lock 'pixels'. * * Return value: - * pointer to the new domain block + * pointer to the new domain block */ { word_t *dst, *pixels; - int y, n; + int y, n; dst = pixels = Calloc (size_of_level (level), sizeof (word_t)); if (domain) for (y = height_of_level (level); y; y--) { - memcpy (dst, domain, width_of_level (level) * sizeof (word_t)); - dst += width_of_level (level); - domain += offset; + memcpy (dst, domain, width_of_level (level) * sizeof (word_t)); + dst += width_of_level (level); + domain += offset; } - else /* state 0 */ + else /* state 0 */ for (n = size_of_level (level); n; n--) - *dst++ = (int) (128 * 8 + .5) * 2; + *dst++ = (int) (128 * 8 + .5) * 2; return pixels; } diff --git a/converter/other/fiasco/codec/dfiasco.c b/converter/other/fiasco/codec/dfiasco.c index 1cdfc672..48c222aa 100644 --- a/converter/other/fiasco/codec/dfiasco.c +++ b/converter/other/fiasco/codec/dfiasco.c @@ -16,6 +16,8 @@ #include <string.h> +#include "nstring.h" + #include "config.h" #include "types.h" diff --git a/converter/other/fiasco/codec/options.c b/converter/other/fiasco/codec/options.c index 77dbaf00..6018a16c 100644 --- a/converter/other/fiasco/codec/options.c +++ b/converter/other/fiasco/codec/options.c @@ -26,6 +26,8 @@ #include <stdio.h> +#include "nstring.h" + #include "types.h" #include "macros.h" #include "error.h" |