📄 ebcot_encoder.c
字号:
}
}
state->A=A; state->C=C; state->word=word; state->rho=rho;
state->available_bits=avail;
}
/*****************************************************************************/
/* STATIC reset_block_contexts */
/*****************************************************************************/
static void
reset_block_contexts(std_short *ctxt, int rows, int cols, int row_gap)
{
register int c;
int outside;
outside = (4-cols) & 3;
row_gap -= (cols + outside);
assert(row_gap > 0);
for (; rows > 0; rows--, ctxt += row_gap)
{
for (c=cols; c > 0; c--)
*(ctxt++) = 0;
for (c=outside; c > 0; c--)
*(ctxt++) = OUT_OF_BOUNDS;
}
}
/*****************************************************************************/
/* STATIC encode_block */
/*****************************************************************************/
static void
encode_block(the_encoder_ref self, ifc_int *sample_buffer,
band_info_ptr band, block_info_ptr info)
/* Encodes a single block of sample values. The actual dimensions of the
block may be found in the `info' structure. The `sample_buffer' array
contains the samples organized in lexicographical fashion, with
consecutive rows of block samples separated by `self->master.row_gap'
samples, which is always larger than the block width. The function
modifies the `info' structure to reflect the locations of the code
words and the rate distortion information associated with the coding
operation. It also updates state information in the `band'
structure. */
{
block_master_ptr master = &(self->master);
code_subblock_ptr sblk;
int block_rows, block_cols;
double delta_wmse, scale_wmse;
int bitplane_idx, last_bitplane, pass_idx;
int last_bytes, n, significant, msb_first;
heap_unit_ptr heap;
int heap_pos;
clock_t cpu_time;
/* Get ready for the coding passes. */
cpu_time = 1; /* prevent warnings from compiler. */
if (master->cpu_time >= 0)
cpu_time = clock();
if (band->band_idx == HL_BAND)
{
master->sample_buffer =
self->sample_buffer_heap_mgr->get_buffer(
self->sample_buffer_heap_mgr);
transpose_sample_buffer(sample_buffer,master->sample_buffer,
info->rows,info->cols,master->row_gap);
block_rows = info->cols;
block_cols = info->rows;
}
else
{
master->sample_buffer = sample_buffer;
block_rows = info->rows;
block_cols = info->cols;
}
for (sblk=master->first_subblock; sblk <= master->last_subblock; sblk++)
{
sblk->significant = 0;
sblk->rows = block_rows - sblk->top_row;
sblk->cols = block_cols - sblk->left_col;
if (sblk->rows > master->max_sub_dim)
sblk->rows = master->max_sub_dim;
if (sblk->cols > master->max_sub_dim)
sblk->cols = master->max_sub_dim;
}
master->zc_lut = band->zc_lut;
master->bit_idx = IMPLEMENTATION_PRECISION-2;
master->block_mag = initialize_quadtree(master);
if (band->heap_tail == NULL)
{
band->next_heap_pos = 0;
band->heap_head = band->heap_tail =
self->code_heap_mgr->get_unit(self->code_heap_mgr);
band->heap_tail->next = NULL;
}
heap = band->heap_tail;
heap_pos = band->next_heap_pos;
ebcot_arith_coder__initialize(&(master->coder_state),heap,heap_pos,
self->code_heap_mgr);
#ifdef LOG_SYMBOLS
master->coder_state.symbol_log = start_symbol_log(band,info);
#endif /* LOG_SYMBOLS */
reset_block_contexts(master->context_buffer,block_rows,block_cols,
master->row_gap);
/* Perform the coding passes. */
scale_wmse = band->step_wmse / ((double)(1<<(band->extra_lsbs<<1)));
scale_wmse *= (1.0 / 64.0); /* Avoid overflow for at least 4 highest
frequency resolution levels. */
scale_wmse *= (double)(1<<(master->bit_idx<<1));
scale_wmse *= 1.0 / ((double)(1<<13));
last_bitplane = master->bit_idx - band->extra_lsbs;
info->insignificant_msbs = 0;
for (delta_wmse=0.0, pass_idx=0, bitplane_idx=0;
bitplane_idx <= last_bitplane;
bitplane_idx++, master->bit_idx--, scale_wmse*=0.25)
{
assert(master->bit_idx > 0);
if ((master->block_mag >> master->bit_idx) & 1)
master->block_update[0] |= QUAD_PARENT_SIGNIFICANT;
significant = (master->block_update[0] & QUAD_PARENT_SIGNIFICANT);
if (significant)
encode_quadtree(master);
else
info->insignificant_msbs++;
for (n=0; n < PASSES_PER_BITPLANE; n++, pass_idx++)
{
block_coding_pass_func pass_function;
if (pass_idx == info->max_passes)
{ bitplane_idx = last_bitplane; break; }
if (significant)
{
pass_function = band->pass_funcs[n];
master->context_mask = band->pass_masks[n];
delta_wmse += ((double) pass_function(master)) * scale_wmse;
if (n == 0)
ebcot_arith_coder__renormalize(&(master->coder_state));
}
assert(pass_idx < MAX_PASSES);
master->cumulative_wmse[pass_idx] = delta_wmse;
master->saved_states[pass_idx] = master->coder_state;
}
}
ebcot_arith_coder__flush(&(master->coder_state));
#ifdef SYMBOL_LOG
fclose(master->coder_state.symbol_log);
master->coder_state.symbol_log = NULL;
#endif /* SYMBOL_LOG */
/* Update state information in `info' and `band' to reflect operations. */
info->first_unit = heap;
info->first_pos = heap_pos;
last_bytes = 0; /* prevent warnings from compiler. */
for (n=0; n < pass_idx; n++)
{
int bits;
bits = ebcot_arith_coder__get_minimum_bits(master->saved_states+n,
heap,heap_pos);
info->passes[n].cumulative_bytes = last_bytes = (bits+7)>>3;
}
assert(last_bytes <= (master->coder_state.saved_words<<2));
compute_rd_slopes(pass_idx,master->cumulative_wmse,
info->passes,master->slope_rates);
for (; pass_idx < info->max_passes; pass_idx++)
{
info->passes[pass_idx].cumulative_bytes = last_bytes;
info->passes[pass_idx].rd_slope = -1;
}
band->heap_tail = master->coder_state.heap;
band->next_heap_pos = master->coder_state.next_heap_pos;
/* End of timed section. */
if (master->cpu_time >= 0)
master->cpu_time += (long int)(clock()-cpu_time);
/* See if code word byte order needs to be reversed. */
msb_first = 1; *((std_byte *)(&msb_first)) = 0;
if (!msb_first)
{ /* Least significant byte appears first in each code word. Need to
reverse this to allow the word buffers to be written out as byte
buffers later when we generate the bit-stream. */
std_int word, *wp;
int heap_remnant;
wp = heap->words + heap_pos;
heap_remnant = HEAP_WORDS - heap_pos;
assert(heap_remnant > 0);
for (n=master->coder_state.saved_words; n > 0; n--)
{
word = *wp;
word = ((word >> 24) & 0x000000FF) | ((word >> 8) & 0x0000FF00) |
((word << 8) & 0x00FF0000) | ((word << 24) & 0xFF000000);
*(wp++) = word;
if ((--heap_remnant) == 0)
{ heap_remnant = HEAP_WORDS; heap=heap->next; wp=heap->words; }
}
}
if (master->sample_buffer != sample_buffer)
self->sample_buffer_heap_mgr->return_buffer(self->sample_buffer_heap_mgr,
master->sample_buffer);
}
/* ========================================================================= */
/* ------------------------- Interface Implementation ---------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* 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;
level_info_ptr lev;
code_subblock_ptr subblock;
int block_dim, block_width, block_height, subblock_dim;
int rows, cols, max_rows, max_cols;
int num_subs, subs_total, context_size;
int comp_idx, n, b, r, c, top_row, left_col;
if (decomposition != DECOMPOSITION__MALLAT)
{
fprintf(stderr,"The current implementation of the EBCOT encoder "
"object\n does not support anything other than Mallat-style "
"decompositions!\n");
exit(-1);
}
*supported_profile = self->profile =
process_profile_flags(required_profile);
get_block_dimensions(argc,argv,&block_dim,&block_height,&subblock_dim);
block_width = block_dim;
self->max_block_height = block_height;
assert(block_width >= block_height);
self->num_levels = levels;
self->num_components = components;
for (max_rows=max_cols=0, comp_idx=0; comp_idx < components; comp_idx++)
{
rows = component_rows[comp_idx];
cols = component_cols[comp_idx];
if (rows > max_rows)
max_rows = rows;
if (cols > max_cols)
max_cols = cols;
}
if (!rd_optimized_truncation_allowed(argc,argv,self->profile))
max_extra_bytes = 100*max_rows*max_cols; /* Something very large. */
get_layer_info(self,argc,argv,dedicated_bytes,max_extra_bytes,
max_rows,max_cols);
self->components = (component_info_ptr)
local_malloc(sizeof(component_info)*(size_t) components);
for (comp_idx=0; comp_idx < components; comp_idx++)
{
comp = self->components + comp_idx;
comp->component_idx = comp_idx;
rows = component_rows[comp_idx];
cols = component_cols[comp_idx];
comp->levels = (level_info_ptr)
local_malloc(sizeof(level_info)*(size_t)(levels+1));
memset(comp->levels,0,sizeof(level_info)*(size_t)(levels+1));
for (lev=comp->levels, n=0; n <= levels; n++, lev++)
{
lev->component_idx = comp_idx;
lev->level_idx = n;
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;
}
}
n = levels; lev = comp->levels + n;
lev->bands[0].band_rows = rows; lev->bands[0].band_cols = cols;
while (n > 0)
{
n--; lev--;
lev->bands[HL_BAND].band_cols =
lev->bands[HH_BAND].band_cols = cols >> 1;
lev->bands[LL_BAND].band_cols =
lev->bands[LH_BAND].band_cols = (cols+1)>>1;
lev->bands[LH_BAND].band_rows =
lev->bands[HH_BAND].band_rows = rows >> 1;
lev->bands[LL_BAND].band_rows =
lev->bands[HL_BAND].band_rows = (rows+1)>>1;
rows = lev->bands[LL_BAND].band_rows;
cols = lev->bands[LL_BAND].band_cols;
}
for (n=0, lev=comp->levels; n <= levels; n++, lev++)
for (b=lev->min_band; b <= lev->max_band; b++)
{ /* Complete band initialization. */
band_info_ptr band = lev->bands + b;
block_info_ptr block;
pass_info_ptr passes;
float step_wmse;
int extra_lsbs, total_blocks, max_passes;
band->component_idx = comp_idx;
band->level_idx = n;
band->band_idx = b;
info->get_quant_info(info,comp_idx,n,b,
NULL,NULL,&step_wmse,&extra_lsbs);
max_passes =
(IMPLEMENTATION_PRECISION-2-extra_lsbs)*PASSES_PER_BITPLANE + 1;
band->blocks_high = 1 + ((band->band_rows-1) / block_height);
band->blocks_wide = 1 + ((band->band_cols-1) / block_width);
band->band_blocks = total_blocks =
band->blocks_high*band->blocks_wide;
band->blocks = block = (block_info_ptr)
local_malloc(sizeof(block_info)*(size_t) total_blocks);
memset(block,0,sizeof(block_info)*(size_t) total_blocks);
passes = (pass_info_ptr)
local_malloc(sizeof(pass_info)*
(size_t)(total_blocks*max_passes));
memset(passes,0,
sizeof(pass_info)*(size_t)(total_blocks*max_passes));
for (top_row=0, r=0; r < band->blocks_high;
r++, top_row+=block_height)
for (left_col=0, c=0; c < band->blocks_wide;
c++, left_col+=block_width, block++, passes+=max_passes)
{ /* Complete block initialization. */
block->top_row = top_row;
block->left_col = left_col;
block->rows = band->band_rows - top_row;
if (block->rows > block_height)
block->rows = block_height;
block->cols = band->band_cols - left_col;
if (block->cols > block_width)
block->cols = block_width;
block->passes = passes;
block->max_passes = max_passes;
}
if (b == HH_BAND)
band->zc_lut = ebcot_diag_zc_lut;
else
band->zc_lut = ebcot_main_zc_lut;
ebcot_set_pass_funcs_and_masks(band,b);
band->step_wmse = step_wmse;
band->extra_lsbs = extra_lsbs;
band->lines.num_lines = 0;
band->lines.info = NULL;
band->lines.buffers = NULL;
}
}
self->output = output;
num_subs = 1 + ((block_dim-1) / subblock_dim);
subblock_dim = 1 + ((block_dim-1) / num_subs);
subs_total = num_subs * num_subs;
self->master.max_dim = block_dim;
self->master.max_sub_dim = subblock_dim;
self->master.row_gap = block_dim + 2;
self->master.first_subblock = subblock = (code_subblock_ptr)
local_malloc(sizeof(code_subblock)*(size_t) subs_total);
self->master.last_subblock = subblock + subs_total - 1;
create_quadtree(num_subs,num_subs,subblock,
&(self->master.first_quad),&(self->master.last_quad));
self->master.block_update = (std_short *) self->master.first_quad;
if (self->master.block_update == NULL)
{
assert(num_subs == 1);
self->master.block_update = (std_short *) subblock;
}
memset(subblock,0,sizeof(code_subblock)*(size_t) subs_total);
for (top_row=0, r=0; r < num_subs; r++, top_row+=subblock_dim)
for (left_col=0, c=0; c < num_subs;
c++, left_col+=subblock_dim, subblock++)
{
subblock->top_row = top_row;
subblock->left_col = left_col;
subblock->offset = top_row*self->master.row_gap + left_col;
}
context_size = self->master.row_gap * (block_dim+2) + 2;
self->master.context_buffer = (std_short *)
local_malloc(sizeof(std_short)*(size_t) context_size);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -