📄 hpbit_stream_in.c
字号:
/*****************************************************************************/
/* Copyright 1998, Hewlett-Packard Company */
/* All rights reserved */
/* File: "hpbit_stream_in.c" */
/* Description: Reference implementation of the `stream_in' object. */
/* Author: David Taubman */
/* Affiliation: Hewlett-Packard and */
/* The University of New South Wales, Australia */
/* Acknowledgements: Partly developed in collaboration with Salma Soudagar */
/* of Motorola, Switzerland, and her colleagues */
/* Version: VM9.0 */
/* Last Revised: 19 April, 2001 */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to avoid the need for byte stuffing when resync */
/* markers are in use. This simplifies the code and substantially improves */
/* the usefulness of the system for applications requiring error resilience. */
/* Copyright 1999 by Hewlett-Packard Company 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 Gene Wu & Michael Gormish to add real markers for COD/COC and */
/* QCD/QCC. */
/* All changes copyright 2000 by Ricoh Silicon Valley with all rights */
/* reserved for the modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to implement changes in Tokyo between CD and */
/* FCD for Part-1 of the standard. Copyrighted by HP with all rights */
/* reserved for the modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to incorporate changes to the POC marker (used */
/* to be POD). Changes are quite extensive and not always explicitly */
/* When flagged, the relevant comment string is "DST POC mod". */
/* Copyright 2000 The University of New South Wales. */
/* All rights reserved for the modified parts. */
/*****************************************************************************/
#include <local_services.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#include <ifc.h>
#include <markers.h>
#include "hpbit_stream_in_local.h"
#include "hpbit_markers.h"
/* ========================================================================= */
/* ------------------------------ Macros ----------------------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* `fetch_data_byte' and `fetch_non_data_byte' */
/*****************************************************************************/
/* Note: file accesses are categorized as data bytes or non-data bytes.
Data accesses occur within the body of a tile-part, i.e. from immediately
after the SOD marker, up until the next SOT or EOC marker, or the end
of the file. Non-data accesses occur everywhere else. In the absence
of errors, non-data accesses correspond exclusively to marker codes. In
the presence of errors, however, we may need to make non-data accesses
to skip over bytes which occur between the nominal end of the most
recent tile-part (as indicated by its length field) and the next marker
code (should be SOT or EOC). */
#define fetch_data_byte(_self,_tp) \
(((_tp->data_bytes_left--) <= 0)? \
(EOF):((_tp->data != NULL)?((int)(*(_tp->data++))):(getc(_self->fp))))
#define fetch_non_data_byte(_self) \
(((((_self->non_data_bytes_left--) <= 0)) && _self->byte_limit_set)? \
(EOF):(getc(_self->fp)))
/* ========================================================================= */
/* -------------------------- Internal Functions --------------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* STATIC return_data_byte */
/*****************************************************************************/
static void
return_data_byte(hpbit_stream_in_ref self, hpbit_tilepart_ptr tp, int val)
/* Can use this function to return one byte previously fetched using
`fetch_data_byte'. No more than one byte may generally be returned. */
{
assert(tp->data_bytes_left < tp->data_bytes);
tp->data_bytes_left++;
if (tp->data != NULL)
{
assert(tp->data > tp->data_handle);
tp->data--;
}
else
{
ungetc(val,self->fp);
}
}
/*****************************************************************************/
/* STATIC read_non_data_bytes */
/*****************************************************************************/
static int
read_non_data_bytes(hpbit_stream_in_ref self, void *buf, int num_bytes)
/* Reads at most `num_bytes' bytes into the supplied buffer and returns
the number of bytes actually read. This may be smaller than `num_bytes'
if the end of file is encountered, or if `self->byte_limit_set' is
true (non-zero) and the limit identified by `self->non_data_bytes_left'
is reached. */
{
if (self->byte_limit_set && (num_bytes > self->non_data_bytes_left))
num_bytes = self->non_data_bytes_left;
if (num_bytes <= 0)
return(0);
num_bytes = fread(buf,1,num_bytes,self->fp);
self->non_data_bytes_left -= num_bytes;
return(num_bytes);
}
/*****************************************************************************/
/* STATIC buffer_remaining_tilepart_bytes */
/*****************************************************************************/
static void
buffer_remaining_tilepart_bytes(hpbit_stream_in_ref self,
hpbit_tilepart_ptr tp)
/* This function reads and buffers any outstanding bytes for the supplied
tile-part (referenced by `tp'). An error is generated if the tile-part
has the `actual_length_unknown' flag set since this suggests that there
should be no more tile-parts in the codestream and hence there should
be no reason to buffer the current tile-part.
The function reads the input file byte by byte until an SOT or EOC
marker is encountered, adjusting the `data_bytes', `data_bytes_left' and
`self->non_data_bytes_left' fields in the event that this delimiting
marker occurs prematurely. */
{
int num_bytes, byte_val, have_ff;
std_byte *buf, *buf_handle;
assert(!self->have_sot);
assert(tp->data == NULL);
if (tp->actual_length_unknown)
local_error("Only the last tile-part in the codestream is allowed to "
"have a zero-valued tile-part length field!");
if (tp->data_bytes_left <= 0)
return;
buf = (std_byte *)
local_malloc(HPBIT_MEM_KEY,tp->data_bytes_left);
buf_handle = buf;
have_ff = 0;
num_bytes = 0;
while ((byte_val = fetch_data_byte(self,tp)) != EOF)
{
*(buf++)= (std_byte) byte_val;
num_bytes++;
if (have_ff)
{
if (byte_val == (MARKER_SOT & 0x00FF))
{
self->have_sot = 1;
num_bytes -= 2;
tp->data_bytes_left += 2;
self->non_data_bytes_left -= 2;
break;
}
else if (byte_val == (MARKER_EOC & 0x00FF))
{
num_bytes -= 2;
tp->data_bytes_left += 2;
self->non_data_bytes_left -= 2;
break;
}
}
have_ff = (byte_val == 0x00FF);
}
if (tp->data_bytes_left >= 0)
{ /* Encountered a premature marker. */
tp->data_bytes -= tp->data_bytes_left;
self->non_data_bytes_left += tp->data_bytes_left;
}
tp->data_bytes_left = num_bytes;
tp->data = tp->data_handle = buf_handle;
}
/*****************************************************************************/
/* STATIC copy_from_big_endian */
/*****************************************************************************/
static void
copy_from_big_endian(void *src, void *dst, int num_words, int precision)
/* Copies the `src' data to the `dst' data and performs and byte reversal
required to convert Big Endian quantities in `src' to quantities with
the current machine's byte order in `src'. */
{
int bigendian, n;
std_byte *sp, *dp;
bigendian = 1;
sp = (std_byte *)(&bigendian);
*sp = 0;
if (bigendian || (precision == 1))
{
memcpy(dst,src,num_words*precision);
return;
}
assert(num_words != 0);
if (precision == 2)
{
for (sp=(std_byte *) src, dp=(std_byte *) dst,
n=num_words; n > 0; n--, sp+=2, dp+=2)
{
dp[0] = sp[1];
dp[1] = sp[0];
}
}
else if (precision == 4)
{
for (sp=(std_byte *) src, dp=(std_byte *) dst,
n=num_words; n > 0; n--, sp+=4, dp+=4)
{
dp[0] = sp[3];
dp[1] = sp[2];
dp[2] = sp[1];
dp[3] = sp[0];
}
}
else
assert(0);
}
/*****************************************************************************/
/* STATIC destroy_pre_marker */
/*****************************************************************************/
static void
destroy_pre_marker(hpbit_pre_marker_ptr pm)
{
hpbit_marker_elt_ptr elt;
while ((elt = pm->elements) != NULL)
{
pm->elements = elt->next;
if (elt->buf != NULL)
local_free(elt->buf);
local_free(elt);
}
local_free(pm);
}
/*****************************************************************************/
/* STATIC destroy_markers */
/*****************************************************************************/
static void
destroy_markers(hpbit_markers_ptr markers, hpbit_tilepart_ptr tp)
{
hpbit_codestream_marker_ptr cp;
hpbit_pre_marker_ptr pm;
while ((cp = markers->codestream_markers) != NULL)
{
markers->codestream_markers = cp->next;
if (cp->accesses == 0)
{
int code;
code = cp->buf[0]; code <<= 8; code += cp->buf[1];
if (tp == NULL)
local_printf(0,76,"Warning: Marker code %0x in global header "
"was not accessed!",code);
else
local_printf(0,76,"Warning: Marker code %0x in tile %d "
"was not accessed!",code,tp->tnum);
}
if(cp->buf != NULL)
local_free(cp->buf);
local_free(cp);
}
while ((pm = markers->pre_markers) != NULL)
{
markers->pre_markers = pm->next;
destroy_pre_marker(pm);
}
if (markers->params.components != NULL)
local_free(markers->params.components);
markers->params.components = NULL;
}
/*****************************************************************************/
/* STATIC destroy_tilepart */
/*****************************************************************************/
static void
destroy_tilepart(hpbit_tilepart_ptr tp)
{
destroy_markers(&(tp->markers),tp);
if (tp->data_handle != NULL)
local_free(tp->data_handle);
local_free(tp);
}
/*****************************************************************************/
/* STATIC read_markers */
/*****************************************************************************/
static std_ushort
read_markers(hpbit_stream_in_ref self, hpbit_tilepart_ptr tp)
/* Reads markers until an appropriate delimiter is encountered, returning
the delimiting marker. The function adds the markers onto the
`codestream_markers' list in the `global_markers' structure within
`self' or the `markers' structure within `tile', depending upon whether
or not `tile' is NULL. Recognized marker section delimiters are
SOT, SOD and EOC. If the file ends before a delimiter is detected,
the function returns 0. */
{
hpbit_markers_ptr markers;
hpbit_codestream_marker_ptr entry, last_entry;
int byte_val, length, n;
/* Begin Aerospace MCT mods (TSW) */
/* std_byte start[4];*/
std_byte start[6];
int pre_len = 4;
/* End Aerospace MCT mods */
if (tp == NULL)
markers = &(self->global_markers);
else
markers = &(tp->markers);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -