📄 hp_dummy_decoder.c
字号:
/*****************************************************************************/
/* Copyright 1998, Hewlett-Packard Company */
/* All rights reserved */
/* Author: David Taubman */
/* Version: V2.0 */
/* Last Revised: 9/22/98 */
/*****************************************************************************/
#include <local_heap.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <line_block_ifc.h>
#define MIN_IFC_INT (((ifc_int) 1)<<(IMPLEMENTATION_PRECISION-1))
/* ========================================================================= */
/* ------------------------------ Definitions ------------------------------ */
/* ========================================================================= */
/******************************** Basic Types ********************************/
#if (INT_MAX == 2147483647)
typedef int std_int;
#elif (LONG_MAX == 2147483647)
typedef long int std_int
#else
#error "Platform does not support 32-bit integers"
#endif
typedef short int std_short;
typedef unsigned char std_byte;
/******************************* Heap Manager ********************************/
#define HEAP_WORDS 64
#define HEAP_BYTES (HEAP_WORDS*4)
#define HEAP_GROUP_UNITS 64
typedef
struct heap_unit {
std_int words[HEAP_WORDS];
struct heap_unit *next;
struct heap_group *group;
int in_use;
} heap_unit, *heap_unit_ptr;
/* This structure is used to manage the dynamic memory consumption
associated with compressed bit-streams. Heap units are managed
within larger `heap_group' structures to minimize the impact of
dynamic memory allocation on implementation efficiency. The
`group' field points to the group to which the heap unit belongs,
while the `in_use' flag indicates whether or not the heap unit
is currently being used to hold compressed bit-stream information. */
typedef
struct heap_group {
heap_unit units[HEAP_GROUP_UNITS];
int free_units;
struct heap_group *next;
} heap_group, *heap_group_ptr;
/* This structure is used to allocate and manage multiple heap units
at once for improved efficiency. All heap units managed by the
encoder/decoder are chained via their `next' fields. */
/***************************** Block Buffering *******************************/
typedef
struct row_of_blocks {
int first_row;
int unfetched_blocks;
ifc_int **rows;
struct row_of_blocks *next;
} row_of_blocks, *row_of_blocks_ptr;
typedef
struct block_buffering {
int block_rows, block_cols;
int blocks_per_row;
row_of_blocks_ptr head, tail;
} block_buffering, *block_buffering_ptr;
/**************************** Subband Structure ******************************/
typedef
struct band_info {
int rows, cols;
int num_bytes;
int consumed_bytes;
heap_unit_ptr store, tail;
std_int consumed_words;
std_int word;
ifc_int extra_bits;
std_int run;
int lines_decoded;
block_buffering blocks;
} band_info, *band_info_ptr;
typedef
struct level_info {
int min_band;
int max_band;
band_info bands[4];
} level_info, *level_info_ptr;
/****************************** Decoder Object *******************************/
typedef
struct component_info {
int num_levels;
level_info_ptr levels;
ifc_int **tree_to_block_map;
} component_info, *component_info_ptr;
typedef
struct the_decoder_obj {
decoder_obj base;
heap_group_ptr heap;
int num_levels;
int num_components;
component_info_ptr components;
int actual_bytes;
} the_decoder_obj, *the_decoder_ref;
/* ========================================================================= */
/* ------------------ Internal non-interface functions --------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* STATIC get_heap_unit */
/*****************************************************************************/
static heap_unit_ptr
get_heap_unit(the_decoder_ref self)
/* Utility function providing efficient management of storage for
holding one or more dynamically growing bitstreams. */
{
heap_group_ptr scan;
heap_unit_ptr unit;
int i;
for (scan=self->heap; scan != NULL; scan=scan->next)
if (scan->free_units)
break;
if (scan == NULL)
{
scan = (heap_group_ptr)
local_malloc(sizeof(heap_group));
scan->next = self->heap;
self->heap = scan;
scan->free_units = HEAP_GROUP_UNITS;
for (unit=scan->units, i=HEAP_GROUP_UNITS; i > 0; i--, unit++)
{
unit->next = NULL;
unit->in_use = 0;
unit->group = scan;
}
}
for (unit=scan->units, i=HEAP_GROUP_UNITS; i > 0; i--, unit++)
if (!unit->in_use)
break;
assert(i > 0);
scan->free_units--;
unit->in_use = 1;
unit->next = NULL;
return(unit);
}
/*****************************************************************************/
/* STATIC return_heap_unit */
/*****************************************************************************/
static void
return_heap_unit(the_decoder_ref self, heap_unit_ptr unit)
/* Utility function; returns bitstream storage allocated
by `get_heap_unit'. */
{
heap_group_ptr group;
group = unit->group;
assert(unit->in_use && (group->free_units < HEAP_GROUP_UNITS));
group->free_units++;
unit->in_use = 0;
}
/*****************************************************************************/
/* STATIC input_word */
/*****************************************************************************/
static void
input_word(the_decoder_ref self, band_info_ptr band)
{
assert(band->consumed_bytes < band->num_bytes);
band->word = band->store->words[band->consumed_words];
band->consumed_words++;
if (band->consumed_words == HEAP_WORDS)
{
heap_unit_ptr tmp;
tmp = band->store;
band->store = tmp->next;
return_heap_unit(self,tmp);
band->consumed_words = 0;
}
}
/*****************************************************************************/
/* STATIC input_byte */
/*****************************************************************************/
static int
input_byte(the_decoder_ref self, band_info_ptr band)
{
int result;
if ((band->consumed_bytes & 3) == 0)
input_word(self,band);
result = (band->word >> 24) & 0x00FF;
band->word <<= 8;
band->consumed_bytes++;
return(result);
}
/*****************************************************************************/
/* STATIC reverse_words */
/*****************************************************************************/
static void
reverse_words(std_int *words, int num_words)
/* Reverses the byte order in each of the `num_words' entries of the `words'
array. */
{
std_int val;
for (; num_words > 0; num_words--, words++)
{
val = *words;
val = ((val >> 24) & 0x000000FF)
| ((val >> 8) & 0x0000FF00)
| ((val << 8) & 0x00FF0000)
| ((val << 24) & 0xFF000000);
*words = val;
}
}
/*****************************************************************************/
/* STATIC destroy_block_buffering */
/*****************************************************************************/
static void
destroy_block_buffering(block_buffering_ptr blocks)
{
row_of_blocks_ptr bp;
int r;
while ((bp=blocks->head) != NULL)
{
blocks->head = bp;
for (r=0; r < blocks->block_rows; r++)
local_free(bp->rows[r]);
local_free(bp->rows);
local_free(bp);
}
}
/* ========================================================================= */
/* ---------- Implementation of dummy_decoder interface functions----------- */
/* ========================================================================= */
/*****************************************************************************/
/* STATIC __initialize */
/*****************************************************************************/
static void
__initialize(decoder_ref base, int decomposition, int levels,
int components, int component_rows[], int component_cols[],
filter_info_ref info, int profile, int dedicated_bytes,
int max_extra_bytes, int max_levels, int max_components,
bitstream_source_ref input, int argc, char *argv[])
{
the_decoder_ref self = (the_decoder_ref) base;
component_info_ptr comp_info;
int comp, n, b, actual_bytes, rows, cols;
level_info_ptr lev;
band_info_ptr band;
int right_endian; /* True if the MSB appears first in each word. */
if (decomposition != DECOMPOSITION__MALLAT)
{
fprintf(stderr,"This simple example decoding engine does not support "
"anything other\n than the standard Mallat decomposition!\n");
exit(-1);
}
assert(profile == (PROFILE__RESOLUTION_PARSABLE |
PROFILE__RESOLUTION_PROGRESSIVE |
PROFILE__COMPONENT_PARSABLE));
/* The bit-stream produced by this coder has only one order, which is
resolution progressive. */
self->num_levels = levels;
self->num_components = components;
self->components = (component_info_ptr)
local_malloc(sizeof(component_info)*(size_t) components);
memset(self->components,0,sizeof(component_info)*(size_t) components);
for (comp=0; comp < components; comp++)
{
comp_info = self->components + comp;
comp_info->num_levels = levels;
rows = component_rows[comp];
cols = component_cols[comp];
comp_info->levels = lev = (level_info_ptr)
local_malloc(sizeof(level_info)*(size_t)(levels+1));
for (n=0; n <= levels; n++, lev++)
{
for (b=0; b < 4; b++)
{
lev->bands[b].num_bytes = 0;
lev->bands[b].consumed_bytes = 0;
lev->bands[b].store = NULL;
lev->bands[b].tail = NULL;
lev->bands[b].consumed_words = 0;
lev->bands[b].word = 0;
lev->bands[b].run = 0;
lev->bands[b].lines_decoded = 0;
lev->bands[b].blocks.head = lev->bands[b].blocks.tail = NULL;
}
lev->min_band = (n==0)?0:1;
lev->max_band = 3;
if (n == levels)
{ /* Special level for whole image to cover degenerate case of a
zero level transform. */
lev->min_band = lev->max_band = 0;
if (levels > 0)
lev->max_band = -1;
}
for (b=lev->min_band; b <= lev->max_band; b++)
{
int extra_bits;
info->get_quant_info(info,comp,n,b,NULL,NULL,NULL,&extra_bits);
lev->bands[b].extra_bits = (ifc_int) extra_bits;
}
}
n--; lev--;
lev->bands[0].rows = rows; lev->bands[0].cols = cols;
for (n--, lev--; n >= 0; n--, lev--)
{
lev->bands[HL_BAND].cols = lev->bands[HH_BAND].cols = cols >> 1;
lev->bands[LL_BAND].cols = lev->bands[LH_BAND].cols = (cols+1)>>1;
lev->bands[LH_BAND].rows = lev->bands[HH_BAND].rows = rows >> 1;
lev->bands[LL_BAND].rows = lev->bands[HL_BAND].rows = (rows+1)>>1;
rows = lev->bands[LL_BAND].rows;
cols = lev->bands[LL_BAND].cols;
}
}
/* Now we read in the bit-stream. */
right_endian = 1;
*((std_byte *)(&right_endian)) = 0;
actual_bytes = 0;
for (n=0; n < levels; n++)
{
for (comp=0; comp < components; comp++)
{
int discard;
discard = 0;
if ((n >= max_levels) || (comp >= max_components) ||
(actual_bytes >= max_extra_bytes))
discard = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -