/* * weights.c: Output of weights * * Written by: Ullrich Hafner * * This file is part of FIASCO (Fractal Image And Sequence COdec) * Copyright (C) 1994-2000 Ullrich Hafner */ /* * $Date: 2000/06/14 20:50:31 $ * $Author: hafner $ * $Revision: 5.1 $ * $State: Exp $ */ #include "config.h" #include "pm_c_util.h" #include "types.h" #include "macros.h" #include "error.h" #include "wfa.h" #include "misc.h" #include "bit-io.h" #include "arith.h" #include "wfalib.h" #include "weights.h" /***************************************************************************** public code *****************************************************************************/ void write_weights (unsigned total, const wfa_t *wfa, bitfile_t *output) /* * Traverse the transition matrices of the 'wfa' and write #'total' * weights != 0 to stream 'output'. * * No return value. */ { unsigned state, label; /* current label */ unsigned offset1, offset2; /* model offsets. */ unsigned offset3, offset4; /* model offsets. */ unsigned *weights_array; /* array of weights to encode */ unsigned *wptr; /* pointer to current weight */ unsigned *level_array; /* array of corresponding levels */ unsigned *lptr; /* pointer to current corr. level */ int min_level, max_level; /* min and max range level */ int d_min_level, d_max_level; /* min and max delta range level */ bool_t dc, d_dc; /* true if dc or delta dc are used */ bool_t delta_approx = NO; /* true if delta has been used */ unsigned delta_count = 0; /* number of delta ranges */ unsigned bits = bits_processed (output); /* * Check whether delta approximation has been used */ for (state = wfa->basis_states; state < wfa->states; state++) if (wfa->delta_state [state]) { delta_approx = YES; break; } /* * Generate array of corresponding levels (context of probability model) */ min_level = d_min_level = MAXLEVEL; max_level = d_max_level = 0; dc = d_dc = NO; for (state = wfa->basis_states; state < wfa->states; state++) for (label = 0; label < MAXLABELS; label++) if (isrange (wfa->tree [state][label])) { if (delta_approx && wfa->delta_state [state]) /* delta approx. */ { d_min_level = MIN(d_min_level, wfa->level_of_state [state] - 1); d_max_level = MAX(d_max_level, wfa->level_of_state [state] - 1); if (wfa->into [state][label][0] == 0) d_dc = YES; } else { min_level = MIN(min_level, wfa->level_of_state [state] - 1); max_level = MAX(max_level, wfa->level_of_state [state] - 1); if (wfa->into [state][label][0] == 0) dc = YES; } } if (min_level > max_level) /* no lc found */ max_level = min_level - 1; if (d_min_level > d_max_level) d_max_level = d_min_level - 1; /* * Context model: * 0 DC weight * 1 Delta DC weight * 2-k normal weights per level * k+1 - m Delta weights per level */ offset1 = dc ? 1 : 0; offset2 = offset1 + (d_dc ? 1 : 0); offset3 = offset2 + (max_level - min_level + 1); offset4 = offset3 + (d_max_level - d_min_level + 1); /* * Weights are encoded as follows: * all weights of state n * sorted by label * sorted by domain number */ wptr = weights_array = Calloc (total, sizeof (unsigned)); lptr = level_array = Calloc (total, sizeof (unsigned)); for (state = wfa->basis_states; state < wfa->states; state++) for (label = 0; label < MAXLABELS; label++) if (isrange (wfa->tree [state][label])) { int edge; /* current edge */ int domain; /* current domain (context of model) */ for (edge = 0; isedge (domain = wfa->into [state][label][edge]); edge++) { if (wptr - weights_array >= (int) total) error ("Can't write more than %d weights.", total); if (domain) /* not DC component */ { if (delta_approx && wfa->delta_state [state]) /* delta */ { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->d_rpf); *lptr++ = offset3 + wfa->level_of_state [state] - 1 - d_min_level; delta_count++; } else { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->rpf); *lptr++ = offset2 + wfa->level_of_state [state] - 1 - min_level; } } else /* DC component */ { if (delta_approx && wfa->delta_state [state]) /* delta */ { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->d_dc_rpf); *lptr++ = offset1; } else { *wptr++ = rtob (wfa->weight [state][label][edge], wfa->wfainfo->dc_rpf); *lptr++ = 0; } } } } { unsigned i; unsigned *c_symbols = Calloc (offset4, sizeof (int)); const int scale = 500; /* scaling of probability model */ c_symbols [0] = 1 << (wfa->wfainfo->dc_rpf->mantissa_bits + 1); if (offset1 != offset2) c_symbols [offset1] = 1 << (wfa->wfainfo->d_dc_rpf->mantissa_bits + 1); for (i = offset2; i < offset3; i++) c_symbols [i] = 1 << (wfa->wfainfo->rpf->mantissa_bits + 1); for (; i < offset4; i++) c_symbols [i] = 1 << (wfa->wfainfo->d_rpf->mantissa_bits + 1); encode_array (output, weights_array, level_array, c_symbols, offset4, total, scale); Free (c_symbols); } debug_message ("%d delta weights out of %d.", delta_count, total); debug_message ("weights: %5d bits. (%5d symbols => %5.2f bps)", bits_processed (output) - bits, total, (bits_processed (output) - bits) / (double) total); Free (weights_array); Free (level_array); }