📄 ref_roi_common.c
字号:
/*****************************************************************************/
/* Copyright 1998, Hewlett-Packard Company */
/* All rights reserved */
/* File: "ref_roi_common.c" */
/* Description: Implementation of common utilities for "ref_forward_roi.c" */
/* and "ref_reverse_roi.c". */
/* Author: David Taubman */
/* Affiliation: Hewlett-Packard and */
/* The University of New South Wales, Australia */
/* Acknowledgements: Partly developed in collaboration with Mathias Larsson */
/* and his colleagues at Ericsson, Sweden */
/* Version: VM8.5 */
/* Last Revised: 11 September, 2000 */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to support arbitrary reference points for the */
/* transform and the various regular partitions, so as to facilitate */
/* cropping and geometric transformations in the compressed domain and to */
/* enable full support for CRF's single-sample overlap Wavelet transform, */
/* as originally documented in Seoul. Changes are too numerous to flag */
/* individually within the code. Changes copyrighted by HP with all rights */
/* reserved for the modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to support interface modifications, arbitrary */
/* changes in coding parameters from component to component and from tile */
/* to tile, to support the full generality of PART-1 of the JPEG2000 */
/* standard, and to support most anticipated generality of PART-2. Changes */
/* are too numerous to flag individually within the code, which in some */
/* places has been completely rewritten. All changes copyrighted by HP with */
/* all rights reserved for the modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified for general wavelet decompositions. */
/* Copyright 2000 Science Applications International Corporation (SAIC). */
/* Copyright 1995 University of Arizona, Arizona Board of Regents. */
/* All Rights Reserved for modified parts. */
/*****************************************************************************/
#include <local_services.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <ifc.h>
#include "ref_roi_common.h"
/* ========================================================================= */
/* ---------------------------- Internal Functions ------------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* STATIC roi_buffer__add_row */
/*****************************************************************************/
static std_byte *
roi_buffer__add_row(roi_buffer_ptr buffer)
/* Adds a new row to the end of the buffer. If a free row is available,
it is re-used; otherwise, the function augments the buffer. A pointer
is returned to the internal row buffer so that the caller can fill
in the contents. */
{
roi_buffered_row_ptr buf;
int r;
/* First, flush out any leading buffer which has a usage count of 0. */
if ((buffer->num_rows > 0) && (buffer->rows->usage_count == 0))
{
roi_buffered_row tmp = buffer->rows[0];
buffer->first_row++;
buffer->num_rows--;
for (r=0; r < buffer->num_rows; r++)
buffer->rows[r] = buffer->rows[r+1];
buffer->rows[r] = tmp;
}
/* Now add the row. */
assert ((buffer->first_row+buffer->num_rows) < buffer->tile_dims.rows);
if (buffer->num_rows >= buffer->max_buffered_rows)
{ /* Augment the buffer. */
int roomy_rows;
assert(buffer->num_rows == buffer->max_buffered_rows); /* Grow 1 by 1 */
buffer->max_buffered_rows++;
roomy_rows = buffer->max_buffered_rows * 2; /* Keep `realloc' fast. */
buffer->rows = (roi_buffered_row_ptr)
local_realloc(buffer->rows,sizeof(roi_buffered_row)*roomy_rows);
buf = buffer->rows + buffer->num_rows;
buf->usage_count = 0;
buf->buf = (std_byte *)
local_malloc(ROI_MEM_KEY,buffer->tile_dims.cols);
}
buf = buffer->rows + buffer->num_rows;
buffer->num_rows++;
buf->usage_count = buffer->usage_count;
return(buf->buf);
}
/*****************************************************************************/
/* STATIC roi_buffer__release_rows */
/*****************************************************************************/
static void
roi_buffer__release_rows(roi_buffer_ptr buffer, int first_row, int num_rows,
int release_count)
/* This function decrements the `usage_count' field of all row buffers
in the indicated range by the `release_count' value. If the count
reaches zero then the buffer is not immediately released, but may be
released on the next call to `roi_buffer__add_row', if any. An error
is generated if the usage count drops below zero. Rows which lie outside
the tile are ignored, but otherwise all rows in the range must belong
to the current moving window. */
{
int idx;
roi_buffered_row_ptr buf;
if (first_row < 0)
{ num_rows += first_row; first_row = 0; }
if ((first_row+num_rows) > buffer->tile_dims.rows)
num_rows = buffer->tile_dims.rows - first_row;
for (; num_rows > 0; num_rows--, first_row++)
{
idx = first_row - buffer->first_row;
assert((idx >= 0) && (idx < buffer->num_rows));
buf = buffer->rows + idx;
buf->usage_count -= release_count;
assert(buf->usage_count >= 0);
}
}
/*****************************************************************************/
/* STATIC roi_buffer__access_rows */
/*****************************************************************************/
static void
roi_buffer__access_rows(roi_buffer_ptr buffer, roi_stage_ref stage,
int first_row, int num_rows, std_byte **buf)
/* Accesses the indicated range of rows from the buffer, returning pointers
to the internal mask buffer for each row via the supplied
`num_rows'-element array, `buf'. If any part of the requested range
of rows lies outside the tile boundaries, the relevant entries in the
`buf' array are set to NULL. If the range includes rows for which the
boost mask is not yet known, the function automatically adds rows and
evaluates their contents. */
{
int null_before, null_after;
int row_idx;
null_before = null_after = 0;
if (first_row < 0)
{ null_before = -first_row; first_row = 0; num_rows -= null_before; }
if ((first_row+num_rows) > buffer->tile_dims.rows)
{ null_after = first_row+num_rows-buffer->tile_dims.rows;
num_rows -= null_after; }
assert(num_rows > 0);
while ((row_idx=buffer->first_row+buffer->num_rows) <
(first_row+num_rows))
{
std_byte *new_row;
int width;
roi_region_ptr region;
new_row = roi_buffer__add_row(buffer);
width = buffer->tile_dims.cols;
if (stage->parent != NULL)
stage->parent->get_mask_line(stage->parent,stage,new_row,width);
else
{ /* Must construct mask from regions. */
memset(new_row,0,(size_t) width);
for (region=stage->regions; region != NULL; region=region->next)
{
std_byte boost, *mp;
int left, right, abs_row_idx;
double val;
abs_row_idx = row_idx + buffer->tile_dims.top_row;
if (region->is_rectangular)
{
if ((abs_row_idx < region->rect.top) ||
(abs_row_idx > region->rect.bottom))
continue;
left = region->rect.left;
right = region->rect.right;
}
else
{
val = (double)(abs_row_idx-region->circle.centre_row);
val = region->circle.radius_squared - val*val;
if (val < 0.0)
continue;
val = sqrt(val);
left = right = (int) floor(val);
left = region->circle.centre_col - left;
right = region->circle.centre_col + right;
}
left -= buffer->tile_dims.left_col;
right -= buffer->tile_dims.left_col;
if (left < 0)
left = 0;
if (right >= buffer->tile_dims.cols)
right = buffer->tile_dims.cols - 1;
boost = (std_byte)(region->boost);
for (mp=new_row+left; left <= right; left++, mp++)
if (*mp < boost)
*mp = boost;
}
}
}
while (null_before--)
*(buf++) = NULL;
row_idx = first_row - buffer->first_row;
for (; num_rows > 0; num_rows--, row_idx++)
*(buf++) = buffer->rows[row_idx].buf;
while (null_after--)
*(buf++) = NULL;
}
/*****************************************************************************/
/* STATIC roi_buffer__terminate */
/*****************************************************************************/
static void
roi_buffer__terminate(roi_buffer_ptr buffer)
/* Deallocates storage managed by the supplied `buffer' structure. */
{
roi_buffered_row_ptr buf;
int r;
for (r=0; r < buffer->max_buffered_rows; r++)
{
buf = buffer->rows + r;
local_free(buf->buf);
}
local_free(buffer->rows);
}
/* ========================================================================= */
/* ---------------------------- Interface Functions ------------------------ */
/* ========================================================================= */
/*****************************************************************************/
/* STATIC __initialize */
/*****************************************************************************/
static void
__initialize(roi_stage_ref self, canvas_dims_ptr tile_dims)
{
self->buffer.tile_dims = *tile_dims;
self->buffer.rows = (roi_buffered_row_ptr)
local_malloc(ROI_MEM_KEY,sizeof(roi_buffered_row));
/* Ensure that realloc works correctly in `add_rows'. */
self->buffer.first_row = 0;
self->buffer.num_rows = 0;
}
/*****************************************************************************/
/* STATIC horizontal__initialize */
/*****************************************************************************/
static void
horizontal__initialize(roi_stage_ref base, canvas_dims_ptr tile_dims)
{
roi_stage_ref branch;
canvas_dims new_dims;
int b, right_col;
__initialize(base,tile_dims);
for (b=0; b < base->horiz_limit; b++)
{
if ((branch=base->branches[b]) != NULL)
{
base->buffer.usage_count++; /* One user for each branch. */
new_dims = *tile_dims;
if (base->horiz_limit > 1) {
right_col = new_dims.left_col + new_dims.cols - 1;
new_dims.left_col = (new_dims.left_col+1-b)>>1;
right_col = (right_col-b)>>1;
new_dims.cols = right_col + 1 - new_dims.left_col;
}
branch->initialize(branch,&new_dims);
}
}
}
/*****************************************************************************/
/* STATIC vertical__initialize */
/*****************************************************************************/
static void
vertical__initialize(roi_stage_ref base, canvas_dims_ptr tile_dims)
{
roi_vertical_ref self = (roi_vertical_ref) base;
roi_stage_ref branch;
canvas_dims new_dims;
int support, val, b, bottom_row;
__initialize(base,tile_dims);
support = base->branch_neg_supports[0] + base->branch_pos_supports[0] + 1;
val = base->branch_neg_supports[1] + base->branch_pos_supports[1] + 1;
if (base->vert_limit > 1)
if ((support < 2) || (val < 2))
local_error("The memory efficient ROI implementation works only "
"for vertical filters whose support spans at least 2 rows!");
if (val > support)
support = val;
self->bufs = (std_byte **)
local_malloc(ROI_MEM_KEY,sizeof(std_byte *)*support);
for (b=0; b < base->vert_limit; b++)
{
self->next_branch_row[b] = 0;
if ((branch=base->branches[b]) != NULL)
{
base->buffer.usage_count++; /* One user for each branch. */
new_dims = *tile_dims;
/* SAIC General Decomp. Begin mods */
if (base->vert_limit > 1) {
bottom_row = new_dims.top_row + new_dims.rows - 1;
new_dims.top_row = (new_dims.top_row+1-b)>>1;
bottom_row = (bottom_row-b)>>1;
new_dims.rows = bottom_row + 1 - new_dims.top_row;
}
/* SAIC General Decomp. End mods */
branch->initialize(branch,&new_dims);
}
}
}
/*****************************************************************************/
/* STATIC band__initialize */
/*****************************************************************************/
static void
band__initialize(roi_stage_ref self, canvas_dims_ptr tile_dims)
{
__initialize(self,tile_dims);
self->buffer.usage_count = tile_dims->cols;
return;
}
/*****************************************************************************/
/* STATIC horizontal__get_mask_line */
/*****************************************************************************/
static void
horizontal__get_mask_line(roi_stage_ref base, roi_stage_ref requester,
std_byte *mask, int width)
{
roi_horizontal_ref self = (roi_horizontal_ref) base;
int b, row_idx, neg, pos, k;
int tile_cols, first_col, last_col, n, idx;
std_byte *src, max;
/* SAIC General Decomp. Begin mods */
if (base->horiz_limit > 1) {
b = (base->branches[0] == requester)?0:1;
assert(base->branches[b] == requester);
first_col = base->buffer.tile_dims.left_col;
last_col = first_col + base->buffer.tile_dims.cols - 1;
tile_cols = last_col+1-first_col;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -