diff options
Diffstat (limited to 'converter/other/fiasco/codec/options.c')
-rw-r--r-- | converter/other/fiasco/codec/options.c | 894 |
1 files changed, 894 insertions, 0 deletions
diff --git a/converter/other/fiasco/codec/options.c b/converter/other/fiasco/codec/options.c new file mode 100644 index 00000000..77dbaf00 --- /dev/null +++ b/converter/other/fiasco/codec/options.c @@ -0,0 +1,894 @@ +/* + * options.c: FIASCO options handling + * + * 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> + */ + +/* + * $Date: 2000/10/28 17:39:31 $ + * $Author: hafner $ + * $Revision: 5.5 $ + * $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 <string.h> +#if STDC_HEADERS +# include <stdlib.h> +#endif /* not STDC_HEADERS */ + +#include <stdio.h> + +#include "types.h" +#include "macros.h" +#include "error.h" + +#include "wfa.h" +#include "misc.h" +#include "bit-io.h" +#include "fiasco.h" +#include "options.h" + +fiasco_c_options_t * +fiasco_c_options_new (void) +/* + * FIASCO options constructor. + * Allocate memory for the FIASCO coder options structure and + * fill in default values. + * + * Return value: + * pointer to the new option structure + */ +{ + c_options_t *options = calloc (1, sizeof (c_options_t)); + fiasco_c_options_t *public = calloc (1, sizeof (fiasco_c_options_t)); + + if (!options || !public) + { + set_error (_("Out of memory.")); + return NULL; + } + public->private = options; + public->delete = fiasco_c_options_delete; + public->set_tiling = fiasco_c_options_set_tiling; + public->set_frame_pattern = fiasco_c_options_set_frame_pattern; + public->set_basisfile = fiasco_c_options_set_basisfile; + public->set_chroma_quality = fiasco_c_options_set_chroma_quality; + public->set_optimizations = fiasco_c_options_set_optimizations; + public->set_video_param = fiasco_c_options_set_video_param; + public->set_quantization = fiasco_c_options_set_quantization; + public->set_progress_meter = fiasco_c_options_set_progress_meter; + public->set_smoothing = fiasco_c_options_set_smoothing; + public->set_title = fiasco_c_options_set_title; + public->set_comment = fiasco_c_options_set_comment; + + strcpy (options->id, "COFIASCO"); + + /* + * Set default value of fiasco options + */ + options->basis_name = strdup ("small.fco"); + options->lc_min_level = 4; + options->lc_max_level = 12; + options->p_min_level = 8; + options->p_max_level = 10; + options->images_level = 5; + options->max_states = MAXSTATES; + options->chroma_max_states = 40; + options->max_elements = MAXEDGES; + options->tiling_exponent = 4; + options->tiling_method = FIASCO_TILING_VARIANCE_DSC; + options->id_domain_pool = strdup ("rle"); + options->id_d_domain_pool = strdup ("rle"); + options->id_rpf_model = strdup ("adaptive"); + options->id_d_rpf_model = strdup ("adaptive"); + options->rpf_mantissa = 3; + options->rpf_range = FIASCO_RPF_RANGE_1_50; + options->dc_rpf_mantissa = 5; + options->dc_rpf_range = FIASCO_RPF_RANGE_1_00; + options->d_rpf_mantissa = 3; + options->d_rpf_range = FIASCO_RPF_RANGE_1_50; + options->d_dc_rpf_mantissa = 5; + options->d_dc_rpf_range = FIASCO_RPF_RANGE_1_00; + options->chroma_decrease = 2.0; + options->prediction = NO; + options->delta_domains = YES; + options->normal_domains = YES; + options->search_range = 16; + options->fps = 25; + options->pattern = strdup ("IPPPPPPPPP"); + options->reference_filename = NULL; + options->half_pixel_prediction = NO; + options->cross_B_search = YES; + options->B_as_past_ref = YES; + options->check_for_underflow = NO; + options->check_for_overflow = NO; + options->second_domain_block = NO; + options->full_search = NO; + options->progress_meter = FIASCO_PROGRESS_NONE; + options->smoothing = 70; + options->comment = strdup (""); + options->title = strdup (""); + + return public; +} + +void +fiasco_c_options_delete (fiasco_c_options_t *options) +/* + * FIASCO options destructor. + * Free memory of FIASCO options struct. + * + * No return value. + * + * Side effects: + * structure 'options' is discarded. + */ +{ + c_options_t *this = cast_c_options (options); + + if (!this) + return; + + Free (this->id_domain_pool); + Free (this->id_d_domain_pool); + Free (this->id_rpf_model); + Free (this->id_d_rpf_model); + Free (this->pattern); + Free (this->comment); + Free (this->title); + + Free (this); + + return; +} + +int +fiasco_c_options_set_tiling (fiasco_c_options_t *options, + fiasco_tiling_e method, unsigned exponent) +/* + * Set tiling `method' and `exponent'. + * See type `fiasco_tiling_e' for a list of valid tiling `methods'. + * The image is subdivied into 2^`exponent' tiles + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + switch (method) + { + case FIASCO_TILING_SPIRAL_ASC: + case FIASCO_TILING_SPIRAL_DSC: + case FIASCO_TILING_VARIANCE_ASC: + case FIASCO_TILING_VARIANCE_DSC: + this->tiling_method = method; + break; + default: + set_error (_("Invalid tiling method `%d' specified " + "(valid methods are 0, 1, 2, or 3)."), method); + return 0; + } + this->tiling_exponent = exponent; + + return 1; +} + +int +fiasco_c_options_set_frame_pattern (fiasco_c_options_t *options, + const char *pattern) +/* + * Set `pattern' of input frames. + * `pattern' has to be a sequence of the following + * characters (case insensitive): + * 'i' intra frame + * 'p' predicted frame + * 'b' bidirectional predicted frame + * E.g. pattern = 'IBBPBBPBB' + * + * When coding video frames the prediction type of input frame N is determined + * by reading `pattern' [N] (`pattern' is periodically extended). + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + else if (!pattern) + { + set_error (_("Parameter `%s' not defined (NULL)."), "pattern"); + return 0; + } + else if (strlen (pattern) < 1) + { + set_error (_("Frame type pattern doesn't contain any character.")); + return 0; + } + else + { + const char *str; + bool_t parse_error = NO; + int c = 0; + + for (str = pattern; *str && !parse_error; str++) + switch (*str) + { + case 'i': + case 'I': + case 'b': + case 'B': + case 'p': + case 'P': + break; + default: + c = *str; + parse_error = YES; + } + + if (parse_error) + { + set_error (_("Frame type pattern contains invalid character `%c' " + "(choose I, B or P)."), c); + return 0; + } + else + { + Free (this->pattern); + this->pattern = strdup (pattern); + + return 1; + } + } +} + +int +fiasco_c_options_set_basisfile (fiasco_c_options_t *options, + const char *filename) +/* + * Set `filename' of FIASCO initial basis. + * + * Return value: + * 1 on success (if the file is readable) + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + else if (!filename) + { + set_error (_("Parameter `%s' not defined (NULL)."), "filename"); + return 0; + } + else + { + /* Skip this because basis file may be linked with program, not + in a separate file. See get_linked_basis(). NETPBM + FILE *file = open_file (filename, "FIASCO_DATA", READ_ACCESS); + if (file) + { + fclose (file); + return 1; + } + else + { + set_error (_("Can't read basis file `%s'.\n%s."), filename, + get_system_error ()); + return 0; + } + */ return 1; + } +} + +int +fiasco_c_options_set_chroma_quality (fiasco_c_options_t *options, + float quality_factor, + unsigned dictionary_size) +/* + * Set color compression parameters. + * When coding chroma channels (Cb and Cr) + * - approximation quality is given by `quality_factor' * `Y quality' and + * - `dictionary_size' gives the number of dictionary elements. + * + * If 'quality' <= 0 then the luminancy coding quality is also during + * chroma channel coding. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + else if (!dictionary_size) + { + set_error (_("Size of chroma compression dictionary has to be " + "a positive number.")); + return 0; + } + else if (quality_factor <= 0) + { + set_error (_("Quality of chroma channel compression has to be " + "positive value.")); + return 0; + } + else + { + this->chroma_decrease = quality_factor; + this->chroma_max_states = dictionary_size; + + return 1; + } +} + +int +fiasco_c_options_set_optimizations (fiasco_c_options_t *options, + unsigned min_block_level, + unsigned max_block_level, + unsigned max_elements, + unsigned dictionary_size, + unsigned optimization_level) +/* + * Set various optimization parameters. + * - During compression only image blocks of size + * {`min_block_level', ... ,`max_block_level'} are considered. + * The smaller this set of blocks is the faster the coder runs + * and the worse the image quality will be. + * - An individual approximation may use at most `max_elements' + * elements of the dictionary which itself contains at most + * `dictionary_size' elements. The smaller these values are + * the faster the coder runs and the worse the image quality will be. + * - `optimization_level' enables some additional low level optimizations. + * 0: standard approximation method + * 1: significantly increases the approximation quality, + * running time is twice as high as with the standard method + * 2: hardly increases the approximation quality of method 1, + * running time is twice as high as with method 1 + * (this method just remains for completeness) + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + else if (!dictionary_size) + { + set_error (_("Size of dictionary has to be a positive number.")); + return 0; + } + else if (!max_elements) + { + set_error (_("At least one dictionary element has to be used " + "in an approximation.")); + return 0; + } + else if (max_block_level < 4) + { + set_error (_("Maximum image block size has to be at least level 4.")); + return 0; + } + else if (min_block_level < 4) + { + set_error (_("Minimum image block size has to be at least level 4.")); + return 0; + } + else if (max_block_level < min_block_level) + { + set_error (_("Maximum block size has to be larger or " + "equal minimum block size.")); + return 0; + } + else + { + this->lc_min_level = min_block_level; + this->lc_max_level = max_block_level; + this->max_states = dictionary_size; + this->max_elements = max_elements; + this->second_domain_block = optimization_level > 0 ? YES : NO; + this->check_for_overflow = optimization_level > 1 ? YES : NO; + this->check_for_underflow = optimization_level > 1 ? YES : NO; + this->full_search = optimization_level > 1 ? YES : NO; + + return 1; + } +} + +int +fiasco_c_options_set_prediction (fiasco_c_options_t *options, + int intra_prediction, + unsigned min_block_level, + unsigned max_block_level) +/* + * Set minimum and maximum size of image block prediction to + * `min_block_level' and `max_block_level'. + * (For either motion compensated prediction of inter frames + * or DC based prediction of intra frames) + * Prediction of intra frames is only used if `intra_prediction' != 0. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + else if (max_block_level < 6) + { + set_error (_("Maximum prediction block size has to be " + "at least level 6")); + return 0; + } + else if (min_block_level < 6) + { + set_error (_("Minimum prediction block size has to be " + "at least level 6")); + return 0; + } + else if (max_block_level < min_block_level) + { + set_error (_("Maximum prediction block size has to be larger or " + "equal minimum block size.")); + return 0; + } + else + { + this->p_min_level = min_block_level; + this->p_max_level = max_block_level; + this->prediction = intra_prediction; + + return 1; + } +} + +int +fiasco_c_options_set_video_param (fiasco_c_options_t *options, + unsigned frames_per_second, + int half_pixel_prediction, + int cross_B_search, + int B_as_past_ref) +/* + * Set various parameters used for video compensation. + * 'frames_per_second' defines the frame rate which should be + * used when the video is decoded. This value has no effect during coding, + * it is just passed to the FIASCO output file. + * If 'half_pixel_prediction' is not 0 then half pixel precise + * motion compensated prediction is used. + * If 'cross_B_search' is not 0 then the fast Cross-B-Search algorithm is + * used to determine the motion vectors of interpolated prediction. Otherwise + * exhaustive search (in the given search range) is used. + * If 'B_as_past_ref' is not 0 then B frames are allowed to be used + * for B frame predicion. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + else + { + this->fps = frames_per_second; + this->half_pixel_prediction = half_pixel_prediction; + this->cross_B_search = cross_B_search; + this->B_as_past_ref = B_as_past_ref; + + return 1; + } +} + +int +fiasco_c_options_set_quantization (fiasco_c_options_t *options, + unsigned mantissa, + fiasco_rpf_range_e range, + unsigned dc_mantissa, + fiasco_rpf_range_e dc_range) +/* + * Set accuracy of coefficients quantization. + * DC coefficients (of the constant dictionary vector f(x,y) = 1) + * are quantized to values of the interval [-`dc_range', `dc_range'] using + * #`dc_mantissa' bits. All other quantized coefficients are quantized in + * an analogous way using the parameters `range' and `mantissa'. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + else if (mantissa < 2 || mantissa > 8 || dc_mantissa < 2 || dc_mantissa > 8) + { + set_error (_("Number of RPF mantissa bits `%d', `%d' have to be in " + "the interval [2,8]."), mantissa, dc_mantissa); + return 0; + } + else + { + if ((range == FIASCO_RPF_RANGE_0_75 + || range == FIASCO_RPF_RANGE_1_00 + || range == FIASCO_RPF_RANGE_1_50 + || range == FIASCO_RPF_RANGE_2_00) + && + (dc_range == FIASCO_RPF_RANGE_0_75 + || dc_range == FIASCO_RPF_RANGE_1_00 + || dc_range == FIASCO_RPF_RANGE_1_50 + || dc_range == FIASCO_RPF_RANGE_2_00)) + { + this->rpf_range = range; + this->dc_rpf_range = dc_range; + this->rpf_mantissa = mantissa; + this->dc_rpf_mantissa = dc_mantissa; + + return 1; + } + else + { + set_error (_("Invalid RPF ranges `%d', `%d' specified."), + range, dc_range); + return 0; + } + } +} + +int +fiasco_c_options_set_progress_meter (fiasco_c_options_t *options, + fiasco_progress_e type) +/* + * Set type of progress meter. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + switch (type) + { + case FIASCO_PROGRESS_BAR: + case FIASCO_PROGRESS_PERCENT: + case FIASCO_PROGRESS_NONE: + this->progress_meter = type; + break; + default: + set_error (_("Invalid progress meter `%d' specified " + "(valid values are 0, 1, or 2)."), type); + return 0; + } + return 1; +} + +int +fiasco_c_options_set_smoothing (fiasco_c_options_t *options, int smoothing) +/* + * Define `smoothing'-percentage along partitioning borders. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + else if (smoothing < -1 || smoothing > 100) + { + set_error (_("Smoothing percentage must be in the range [-1, 100].")); + return 0; + } + else + { + this->smoothing = smoothing; + return 1; + } +} + +int +fiasco_c_options_set_comment (fiasco_c_options_t *options, const char *comment) +/* + * Define `comment' of FIASCO stream. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + else if (!comment) + { + set_error (_("Parameter `%s' not defined (NULL)."), "title"); + return 0; + } + else + { + this->comment = strdup (comment); + return 1; + } +} + +int +fiasco_c_options_set_title (fiasco_c_options_t *options, const char *title) +/* + * Define `title' of FIASCO stream. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + c_options_t *this = (c_options_t *) cast_c_options (options); + + if (!this) + { + return 0; + } + else if (!title) + { + set_error (_("Parameter `%s' not defined (NULL)."), "title"); + return 0; + } + else + { + this->title = strdup (title); + return 1; + } +} + +c_options_t * +cast_c_options (fiasco_c_options_t *options) +/* + * Cast generic pointer `options' to type c_options_t. + * Check whether `options' is a valid object of type c_options_t. + * + * Return value: + * pointer to options struct on success + * NULL otherwise + */ +{ + c_options_t *this = (c_options_t *) options->private; + if (this) + { + if (!streq (this->id, "COFIASCO")) + { + set_error (_("Parameter `options' doesn't match required type.")); + return NULL; + } + } + else + { + set_error (_("Parameter `%s' not defined (NULL)."), "options"); + } + + return this; +} + +/************************************************************************** +*************************************************************************** + DECODER +*************************************************************************** +**************************************************************************/ + +fiasco_d_options_t * +fiasco_d_options_new (void) +/* + * FIASCO options constructor. + * Allocate memory for the FIASCO coder options structure and + * fill in default values. + * + * Return value: + * pointer to the new option structure + */ +{ + d_options_t *options = calloc (1, sizeof (d_options_t)); + fiasco_d_options_t *public = calloc (1, sizeof (fiasco_d_options_t)); + + if (!options || !public) + { + set_error (_("Out of memory.")); + return NULL; + } + public->private = options; + public->delete = fiasco_d_options_delete; + public->set_smoothing = fiasco_d_options_set_smoothing; + public->set_magnification = fiasco_d_options_set_magnification; + public->set_4_2_0_format = fiasco_d_options_set_4_2_0_format; + + strcpy (options->id, "DOFIASCO"); + + /* + * Set default value of fiasco decoder options + */ + options->smoothing = 70; + options->magnification = 0; + options->image_format = FORMAT_4_4_4; + + return public; +} + +void +fiasco_d_options_delete (fiasco_d_options_t *options) +/* + * FIASCO options destructor. + * Free memory of FIASCO options struct. + * + * No return value. + * + * Side effects: + * structure 'options' is discarded. + */ +{ + d_options_t *this = cast_d_options (options); + + if (!this) + return; + + Free (this); + + return; +} + +int +fiasco_d_options_set_smoothing (fiasco_d_options_t *options, int smoothing) +/* + * Define `smoothing'-percentage along partitioning borders. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + d_options_t *this = (d_options_t *) cast_d_options (options); + + if (!this) + { + return 0; + } + else if (smoothing < -1 || smoothing > 100) + { + set_error (_("Smoothing percentage must be in the range [-1, 100].")); + return 0; + } + else + { + this->smoothing = smoothing; + return 1; + } +} + +int +fiasco_d_options_set_magnification (fiasco_d_options_t *options, int level) +/* + * Set magnification-'level' of decoded image. + * 0: width x height of original image + * 1: (2 * width) x (2 * height) of original image + * -1: (width / 2 ) x (height / 2) of original image + * etc. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + d_options_t *this = (d_options_t *) cast_d_options (options); + + if (!this) + { + return 0; + } + else + { + this->magnification = level; + return 1; + } +} + +int +fiasco_d_options_set_4_2_0_format (fiasco_d_options_t *options, int format) +/* + * Set image format to 4:2:0 or 4:4:4. + * + * Return value: + * 1 on success + * 0 otherwise + */ +{ + d_options_t *this = (d_options_t *) cast_d_options (options); + + if (!this) + { + return 0; + } + else + { + this->image_format = format ? FORMAT_4_2_0 : FORMAT_4_4_4; + return 1; + } +} + +d_options_t * +cast_d_options (fiasco_d_options_t *options) +/* + * Cast generic pointer `options' to type d_options_t. + * Check whether `options' is a valid object of type d_options_t. + * + * Return value: + * pointer to options struct on success + * NULL otherwise + */ +{ + d_options_t *this = (d_options_t *) options->private; + + if (this) + { + if (!streq (this->id, "DOFIASCO")) + { + set_error (_("Parameter `options' doesn't match required type.")); + return NULL; + } + } + else + { + set_error (_("Parameter `%s' not defined (NULL)."), "options"); + } + + return this; +} + + |