📄 coder.c
字号:
/* * coder.c: WFA coder toplevel functions * * Written by: Ullrich Hafner * * This file is part of FIASCO (獸籸actal 獻籱age 獳籲d 玈籩quence 獵O籨ec) * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> *//* * $Date: 2000/06/14 20:50:51 $ * $Author: hafner $ * $Revision: 5.1 $ * $State: Exp $ */#define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */#include "config.h"#include "pnm.h"#include <math.h>#include <ctype.h>#include <string.h>#include "nstring.h"#include "types.h"#include "macros.h"#include "error.h"#include "fiasco.h"#include "cwfa.h"#include "misc.h"#include "control.h"#include "bintree.h"#include "subdivide.h"#include "read.h"#include "write.h"#include "image.h"#include "mwfa.h"#include "list.h"#include "decoder.h"#include "motion.h"#include "wfalib.h"#include "domain-pool.h"#include "coeff.h"#include "coder.h"#include "rpf.h"/***************************************************************************** global variables *****************************************************************************/const real_t MAXCOSTS = 1e20;/***************************************************************************** prototypes *****************************************************************************/static coding_t *alloc_coder (char const * const *inputname, const c_options_t *options, wfa_info_t *wi);static voidfree_coder (coding_t *c);static char *get_input_image_name (char const * const *templptr, unsigned ith_image);static voidvideo_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 voidprint_statistics (char c, real_t costs, const wfa_t *wfa, const image_t *image, const range_t *range);static frame_type_epattern2type (unsigned frame, const char *pattern);/***************************************************************************** public code *****************************************************************************/intfiasco_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; /* * 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; }}/***************************************************************************** private code *****************************************************************************/static coding_t *alloc_coder (char const * const *inputname, const c_options_t *options, wfa_info_t *wi)/* * 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 */{ coding_t *c = NULL; /* * 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; 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; } /* * Levels ... */ { unsigned lx, ly; 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); } 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->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 (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; /* * 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 *)); 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); /* * 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); /* * 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; c->mt = alloc_motion (wi); return c;}static voidfree_coder (coding_t *c)/* * Coder struct destructor: * Free memory of 'coder' struct. * * No return value. * * Side effects: * structure 'coder' is discarded. */{ free_tiling (c->tiling); free_motion (c->mt); Free (c->pixels); Free (c->images_of_state); Free (c->ip_images_state); Free (c->ip_states_state); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -