/*
* write.c: Output of WFA files
*
* Written by: Ullrich Hafner
*
* This file is part of FIASCO (Fractal Image And Sequence COdec)
* Copyright (C) 1994-2000 Ullrich Hafner
*/
/*
* $Date: 2000/07/18 15:44:59 $
* $Author: hafner $
* $Revision: 5.3 $
* $State: Exp $
*/
#include "config.h"
#include "types.h"
#include "macros.h"
#include "error.h"
#include "cwfa.h"
#include "image.h"
#include "misc.h"
#include "bit-io.h"
#include "rpf.h"
#include "tree.h"
#include "matrices.h"
#include "weights.h"
#include "mc.h"
#include "nd.h"
#include "write.h"
/*****************************************************************************
prototypes
*****************************************************************************/
static void
write_tiling (const tiling_t *tiling, bitfile_t *output);
/*****************************************************************************
public code
*****************************************************************************/
void
write_next_wfa (const wfa_t *wfa, const coding_t *c, bitfile_t *output)
/*
* Write 'wfa' to stream 'output'. If the first frame should be written
* then also store the header information of the coding struct 'c'.
*
* No return value.
*/
{
unsigned edges = 0; /* number of transitions */
unsigned bits;
debug_message ("--------------------------------------"
"--------------------------------------");
if (c->mt->number == 0) /* first WFA */
write_header (wfa->wfainfo, output);
bits = bits_processed (output);
/*
* Frame header information
*/
{
const int rice_k = 8; /* parameter of Rice Code */
write_rice_code (wfa->states, rice_k, output);
write_rice_code (c->mt->frame_type, rice_k, output);
write_rice_code (c->mt->number, rice_k, output);
}
OUTPUT_BYTE_ALIGN (output);
debug_message ("frame-header: %5d bits.", bits_processed (output) - bits);
if (c->tiling->exponent) /* write tiling permutation */
{
put_bit (output, 1);
write_tiling (c->tiling, output);
}
else
put_bit (output, 0);
OUTPUT_BYTE_ALIGN (output);
write_tree (wfa, output);
if (c->options.prediction) /* write nondeterministic approx. */
{
put_bit (output, 1);
write_nd (wfa, output);
}
else
put_bit (output, 0);
if (c->mt->frame_type != I_FRAME) /* write motion compensation info */
write_mc (c->mt->frame_type, wfa, output);
edges = write_matrices (c->options.normal_domains,
c->options.delta_domains, wfa, output);
if (edges) /* found at least one approximation */
write_weights (edges, wfa, output);
debug_message ("--------------------------------------"
"--------------------------------------");
}
void
write_header (const wfa_info_t *wi, bitfile_t *output)
/*
* Write the header information describing the type of 'wfa'
* to stream 'output'.
*
* No return value.
*/
{
const unsigned rice_k = 8; /* parameter of Rice Code */
unsigned bits = bits_processed (output);
const char *text; /* next character to write */
/*
* Write magic number and name of initial basis
*/
for (text = FIASCO_MAGIC; *text; text++)
put_bits (output, *text, 8);
put_bits (output, '\n', 8);
for (text = wi->basis_name; *text; text++)
put_bits (output, *text, 8);
put_bits (output, *text, 8);
write_rice_code (FIASCO_BINFILE_RELEASE, rice_k, output);
write_rice_code (HEADER_TITLE, rice_k, output);
for (text = wi->title;
text && *text && text - wi->title < MAXSTRLEN - 2;
text++)
put_bits (output, *text, 8);
put_bits (output, 0, 8);
write_rice_code (HEADER_COMMENT, rice_k, output);
for (text = wi->comment;
text && *text && text - wi->comment < MAXSTRLEN - 2;
text++)
put_bits (output, *text, 8);
put_bits (output, 0, 8);
write_rice_code (HEADER_END, rice_k, output);
write_rice_code (wi->max_states, rice_k, output);
put_bit (output, wi->color ? 1 : 0);
write_rice_code (wi->width, rice_k, output);
write_rice_code (wi->height, rice_k, output);
if (wi->color)
write_rice_code (wi->chroma_max_states, rice_k, output);
write_rice_code (wi->p_min_level, rice_k, output);
write_rice_code (wi->p_max_level, rice_k, output);
write_rice_code (wi->frames, rice_k, output);
write_rice_code (wi->smoothing, rice_k, output);
put_bits (output, wi->rpf->mantissa_bits - 2, 3);
put_bits (output, wi->rpf->range_e, 2);
if (wi->rpf->mantissa_bits != wi->dc_rpf->mantissa_bits ||
wi->rpf->range != wi->dc_rpf->range)
{
put_bit (output, YES);
put_bits (output, wi->dc_rpf->mantissa_bits - 2, 3);
put_bits (output, wi->dc_rpf->range_e, 2);
}
else
put_bit (output, NO);
if (wi->rpf->mantissa_bits != wi->d_rpf->mantissa_bits ||
wi->rpf->range != wi->d_rpf->range)
{
put_bit (output, YES);
put_bits (output, wi->d_rpf->mantissa_bits - 2, 3);
put_bits (output, wi->d_rpf->range_e, 2);
}
else
put_bit (output, NO);
if (wi->dc_rpf->mantissa_bits != wi->d_dc_rpf->mantissa_bits ||
wi->dc_rpf->range != wi->d_dc_rpf->range)
{
put_bit (output, YES);
put_bits (output, wi->d_dc_rpf->mantissa_bits - 2, 3);
put_bits (output, wi->d_dc_rpf->range_e, 2);
}
else
put_bit (output, NO);
if (wi->frames > 1) /* motion compensation stuff */
{
write_rice_code (wi->fps, rice_k, output);
write_rice_code (wi->search_range, rice_k, output);
put_bit (output, wi->half_pixel ? 1 : 0);
put_bit (output, wi->B_as_past_ref ? 1 : 0);
}
OUTPUT_BYTE_ALIGN (output);
debug_message ("header: %d bits.", bits_processed (output) - bits);
}
/*****************************************************************************
private code
*****************************************************************************/
static void
write_tiling (const tiling_t *tiling, bitfile_t *output)
/*
* Write image tiling information given by 'tiling' to stream 'output'.
*
* No return value.
*/
{
const unsigned rice_k = 8; /* parameter of Rice Code */
unsigned bits = bits_processed (output);
write_rice_code (tiling->exponent, rice_k, output);
if (tiling->method == FIASCO_TILING_VARIANCE_ASC
|| tiling->method == FIASCO_TILING_VARIANCE_DSC)
{
unsigned tile; /* current image tile */
put_bit (output, 1);
for (tile = 0; tile < 1U << tiling->exponent; tile++)
if (tiling->vorder [tile] != -1) /* image tile is visible */
put_bits (output, tiling->vorder [tile], tiling->exponent);
}
else
{
put_bit (output, 0);
put_bit (output, tiling->method == FIASCO_TILING_SPIRAL_ASC);
}
debug_message ("tiling: %4d bits.", bits_processed (output) - bits);
}