📄 hp_dummy_encoder.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))
#define MAX_IFC_MAG ((ifc_int)(~MIN_IFC_INT))
/* ========================================================================= */
/* ------------------------------ 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 unfilled_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;
heap_unit_ptr store, tail;
std_int remaining_words;
std_int word;
ifc_int extra_bits;
std_int run;
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;
/****************************** Encoder 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_encoder_obj {
encoder_obj base;
heap_group_ptr heap;
int num_levels;
int num_components;
component_info_ptr components;
bitstream_sink_ref output;
} the_encoder_obj, *the_encoder_ref;
/* ========================================================================= */
/* ------------------ Internal non-interface functions --------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* STATIC get_heap_unit */
/*****************************************************************************/
static heap_unit_ptr
get_heap_unit(the_encoder_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_encoder_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 output_word */
/*****************************************************************************/
static void
output_word(the_encoder_ref self, band_info_ptr band)
{
if (band->remaining_words == 0)
{
heap_unit_ptr unit;
unit = get_heap_unit(self);
unit->next = NULL;
if (band->tail == NULL)
band->store = band->tail = unit;
else
band->tail = band->tail->next = unit;
band->remaining_words = HEAP_WORDS;
}
band->tail->words[HEAP_WORDS-band->remaining_words] = band->word;
band->remaining_words--;
band->word = 0;
}
/*****************************************************************************/
/* STATIC output_byte */
/*****************************************************************************/
static void
output_byte(the_encoder_ref self, band_info_ptr band, int byte)
{
band->num_bytes++;
band->word <<= 8;
band->word |= (byte & 0x00FF);
if ((band->num_bytes & 3) == 0)
output_word(self,band);
}
/*****************************************************************************/
/* 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_encoder interface functions----------- */
/* ========================================================================= */
/*****************************************************************************/
/* STATIC __initialize */
/*****************************************************************************/
static void
__initialize(encoder_ref base, int decomposition, int levels, int components,
int component_rows[], int component_cols[],
filter_info_ref info, int required_profile,
int *supported_profile, int dedicated_bytes,
int max_extra_bytes, bitstream_sink_ref output,
int argc, char *argv[])
{
the_encoder_ref self = (the_encoder_ref) base;
component_info_ptr comp_info;
level_info_ptr lev;
int n, b, comp, profile_flags, rows, cols;
if (decomposition != DECOMPOSITION__MALLAT)
{
fprintf(stderr,"This simple example coding engine does not support "
"anything other\n than the standard Mallat decomposition!\n");
exit(-1);
}
profile_flags = PROFILE__RESOLUTION_PROGRESSIVE;
profile_flags |= PROFILE__RESOLUTION_PARSABLE;
profile_flags |= PROFILE__COMPONENT_PARSABLE;
if (required_profile & ~profile_flags)
{
fprintf(stderr,"This \"dummy\" coder is non-embedded. It supports "
"neither\n random access, nor SNR scalability!\n");
exit(-1);
}
*supported_profile = profile_flags;
self->num_levels = levels;
self->num_components = components;
self->output = output;
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++)
{
rows = component_rows[comp];
cols = component_cols[comp];
comp_info = self->components + comp;
comp_info->num_levels = levels;
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].rows = lev->bands[b].cols = 0;
lev->bands[b].num_bytes = 0;
lev->bands[b].store = NULL;
lev->bands[b].tail = NULL;
lev->bands[b].remaining_words = 0;
lev->bands[b].word = 0;
lev->bands[b].run = 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -