📄 compress.c
字号:
/*****************************************************************************/
/* Copyright 1998, Hewlett-Packard Company */
/* All rights reserved */
/* File: "compress.c" */
/* Description: Invocation environment for compression. */
/* Author: David Taubman */
/* Affiliation: Hewlett-Packard and */
/* The University of New South Wales, Australia */
/* Version: VM8.5 */
/* Last Revised: 11 September, 2000 */
/*****************************************************************************/
/*****************************************************************************/
/* Modified to incorporate optional entropy coder */
/* Copyright 1999 Science Applications International Corporation (SAIC). */
/* All Rights Reserved for modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified to include Lagrangian Rate Allocation */
/* Copyright 1999 Fujifilm Software Colifornia Inc. */
/* Copyright 1999 Science Applications International Corporation (SAIC). */
/* Copyright 1995 University of Arizona, Arizona Board of Regents. */
/* All Rights Reserved for modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* 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 by David Taubman to allow overlapping tiles. 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. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified for general offset and scalar quantization. */
/* Copyright 2000 The MITRE Corporation. */
/* All Rights Reserved for modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Compilation directives involving "_WIN32" added by David Taubman to avoid */
/* problems caused by EKC raw image I/O code. */
/*****************************************************************************/
/*****************************************************************************/
/* Compilation problems caused by EKC raw image I/O code should hopefully be */
/* fixed. Therefore, compilation directives involving "_WIN32" added by */
/* David Taubman have been taken out. */
/*****************************************************************************/
#include <local_services.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <ifc.h>
#include <image_io.h>
#include <markers.h>
#include "compress_local.h"
/* STOP: THERE SHOULD HARDLY EVER BE ANY REASON TO CHANGE THIS FILE.
IF YOU ARE ABOUT TO DO SO THEN YOU HAVE PROBABLY NOT UNDERSTOOD
THE MODULAR PRINCIPLES BEHIND VM3A. */
/* ========================================================================= */
/* -------------------------- Internal Functions --------------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* STATIC get_image_row */
/*****************************************************************************/
static ifc_int *get_image_row(enc_component_info_ptr component,int comp_idx,
int idx,image_reader_ref reader)
/* This function returns a pointer to a buffered image row whose
location, relative to the start of the current vertical tile
partition is given by `idx'. Legal values of `idx' may range from
-1 through to `component->tile_rows', since there may be an overlap
of up to 1 row at the top or bottom of the tile partition. */
{
int r;
assert((idx >= -1) && (idx <= component->tile_rows));
idx -= component->min_buffer_row_idx;
assert(idx >= 0);
while ((r = component->num_buffer_rows) <= idx)
{
component->num_buffer_rows++;
if (component->num_buffer_rows > component->max_buffer_rows)
{
component->max_buffer_rows++;
component->buffer = (ifc_int **)local_realloc(component->buffer,
sizeof(ifc_int *)*component->max_buffer_rows);
component->buffer[r] = (ifc_int *)local_malloc(INVOCATION_MEM_KEY,
sizeof(ifc_int)*component->cols);
}
reader->pull_line(reader,component->buffer[r],comp_idx,component->cols);
}
return(component->buffer[idx]);
}
/*****************************************************************************/
/* STATIC release_image_row */
/*****************************************************************************/
static void release_image_row(enc_component_info_ptr component, int idx)
/* This function is called when we can be sure that the indicated image
row will not be accessed again. By assumption, none of the preceding
rows will be accessed again either. The row itself is identified
relative to the start of the current vertical tile partition, so the
`idx' value may be negative. If the row is not currently in the buffer
then no action is taken. */
{
int r, k;
ifc_int *tmp;
idx -= component->min_buffer_row_idx;
assert(idx<component->num_buffer_rows);
for(r=0;r<=idx;r++){
/* Release row `r'. */
component->min_buffer_row_idx++;
component->num_buffer_rows--;
tmp = component->buffer[0];
for(k=0;k<component->num_buffer_rows;k++)
component->buffer[k] = component->buffer[k+1];
component->buffer[k] = tmp;
}
}
/*****************************************************************************/
/* STATIC read_and_compress_the_image */
/*****************************************************************************/
static void
read_and_compress_the_image(forward_info_ref info,image_reader_ref reader,
component_mix_ref mixer,int num_components)
{
enc_component_info_ptr comps;
int n, max_rows, max_cols, precision, done;
int tnum, xnum, ynum;
int tiles_across=0, tiles_down=0; /* TJF: =0 to avoid warnings */
ifc_int *buf, *work;
/* Initialize component information structures with basic details first. */
comps = (enc_component_info_ptr)local_malloc(INVOCATION_MEM_KEY,
sizeof(enc_component_info)*num_components);
max_rows = max_cols = 0;
for(n=0;n<num_components;n++){
canvas_dims dims;
tnum = 0;
tiles_across = tiles_down = 0;
/* MITRE General Offset/SQ Begin */ /* Begin Aerospace MCT mods */
while (info->get_fixed_tile_info(info,n,tnum,&xnum,&ynum,&dims,
NULL,NULL,NULL,NULL,NULL,&precision,NULL)){
/* MITRE General Offset/SQ End */ /* End Aerospace MCT mods */
if(xnum==0){
comps[n].rows+=dims.rows;
tiles_down++;
}
if(ynum==0){
comps[n].cols+=dims.cols;
tiles_across++;
}
if(dims.cols>max_cols)
max_cols=dims.cols;
tnum++;
}
if(comps[n].rows>max_rows)
max_rows=comps[n].rows;
comps[n].max_buffer_rows=1;
comps[n].buffer=(ifc_int **)
local_malloc(INVOCATION_MEM_KEY,sizeof(ifc_int *));
comps[n].buffer[0]=(ifc_int *)
local_malloc(INVOCATION_MEM_KEY,sizeof(ifc_int)*comps[n].cols);
}
work=(ifc_int *)
local_malloc(INVOCATION_MEM_KEY,sizeof(ifc_int)*(max_cols+2));
/* Now set the relative line processing rates for the components to
maximize locality in row accesses from multiple component images. */
for(n=0;n<num_components;n++)
comps[n].line_rate = ((float)(comps[n].rows))/((float) max_rows);
/* Now walk through the tiles in scan-line order. */
for(tnum=0,ynum=0;ynum<tiles_down;ynum++){
for(n=0;n<num_components;n++){
/* Set up new vertical tile partition. */
if(ynum==0){
comps[n].min_buffer_row_idx=0;
comps[n].num_buffer_rows=0;
}
else
comps[n].min_buffer_row_idx-=comps[n].tile_rows;
comps[n].row_offset = 0;
}
for(xnum=0;xnum<tiles_across;xnum++,tnum++){
/* Set up tile-specific parameters. */
/* Begin Aerospace MCT mods (TSW) */
int multicomp_used;
/* End Aerospace MCT mods */
for(n=0;n<num_components;n++){
canvas_dims fix_dims, var_dims;
int upshift; /* MITRE */
double dc_offset; /* MITRE */
/* MITRE General Offset/SQ Begin */ /* Begin Aerospace MCT mods */
info->get_fixed_tile_info(info,n,tnum,NULL,NULL,&fix_dims,
NULL,NULL,NULL,NULL,NULL,&precision,&multicomp_used);
/* MITRE General Offset/SQ End */ /* End Aerospace MCT mods */
info->get_var_tile_info(info,n,NULL,&var_dims,NULL,&upshift,
&dc_offset);
local_printf( 0,76, "Comp %d Tile %d Offset %lg\n", n, tnum,
dc_offset);
comps[n].offset=-dc_offset;
comps[n].tile_rows=fix_dims.rows;
comps[n].tile_cols=fix_dims.cols;
comps[n].upshift=(ifc_int) upshift;
comps[n].ovlp_top=fix_dims.top_row-var_dims.top_row;
comps[n].ovlp_left=fix_dims.left_col-var_dims.left_col;
comps[n].ovlp_bottom=var_dims.rows-fix_dims.rows
-comps[n].ovlp_top;
comps[n].ovlp_right=var_dims.cols-fix_dims.cols
-comps[n].ovlp_left;
assert(((comps[n].ovlp_top & ~1)==0)&&
((comps[n].ovlp_bottom & ~1)==0)&&
((comps[n].ovlp_left & ~1)==0)&&
((comps[n].ovlp_right & ~1)==0));
comps[n].line_remainder=0.0F;
comps[n].tile_row_idx=0;
comps[n].max_tile_row_idx=comps[n].tile_rows-1;
if(comps[n].ovlp_top){
assert(ynum>0);
comps[n].tile_row_idx--;
}
if(comps[n].ovlp_bottom){
assert(ynum<(tiles_down-1));
comps[n].max_tile_row_idx++;
}
}
/* Now push lines into the tile components in a synchronized
fashion. */
do{
done=1;
for(n=0;n<num_components;n++){
int tile_cols,r;
ifc_int *sp,offset,upshift,val;
if(comps[n].tile_row_idx>comps[n].max_tile_row_idx)
continue;
done=0;
comps[n].line_remainder-=comps[n].line_rate;
if(comps[n].line_remainder>=0.0F)
continue;
comps[n].line_remainder+=1.0F;
r=comps[n].tile_row_idx++;
if(xnum==(tiles_across-1))
release_image_row(comps+n,r-1-comps[n].ovlp_bottom);
buf=get_image_row(comps+n,n,r,reader);
assert(comps[n].row_offset>=comps[n].ovlp_left);
buf+=comps[n].row_offset-comps[n].ovlp_left;
tile_cols=comps[n].tile_cols+
(comps[n].ovlp_left+comps[n].ovlp_right);
assert(comps[n].row_offset-comps[n].ovlp_left+tile_cols<=\
comps[n].cols);
assert(tile_cols<=(max_cols+2));
memcpy(work,buf,(size_t)(sizeof(ifc_int)*tile_cols));
upshift=comps[n].upshift;
/* Originally this expression mixed doubles and integers */
/* and assigned to an integer. Changed this to a rounding */
/* operation which I believe is correct (JHK). */
offset=(short)floor((comps[n].offset)*(1<<upshift)+0.5);
/* Begin Aerospace MCT mods (TSW) */
/* For multicomponent transforms, the upshift operation
must be delayed until after computation of the transform.
Check if it is used for this tile before performing. */
if ( multicomp_used == 0 ) {
if(upshift>=0){
/* Originally this expression mixed doubles and */
/* integers and assigned to an integer. Changed this */
/* to a rounding operation which I believe is correct */
/* (JHK). */
offset=
(short) floor((comps[n].offset)*(1<<upshift)+0.5);
for(sp=work,r=tile_cols;r>0;r--){
val=*sp;
val<<=upshift;
val+=offset;
*(sp++)=val;
}
}
else{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -