📄 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: VM6.0 *//* Last Revised: 27 January, 2000 *//*****************************************************************************//*****************************************************************************//* 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. *//*****************************************************************************/#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 SOS marker, up until the next SOT or EOI 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 EOI). */#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 EOI 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_EOI & 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); } 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, SOS and EOI. 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; std_byte start[4]; if (tp == NULL) markers = &(self->global_markers); else markers = &(tp->markers); last_entry = NULL; do { byte_val = 0; while (byte_val != 0x00FF) { byte_val = fetch_non_data_byte(self); if (byte_val == EOF) return(0); } if ((byte_val = fetch_non_data_byte(self)) == EOF) return(0); if (byte_val == (MARKER_SOS & 0x00FF)) return(MARKER_SOS); if (byte_val == (MARKER_SOT & 0x00FF)) { self->have_sot = 1; return(MARKER_SOT); } if (byte_val == (MARKER_EOI & 0x00FF)) return(MARKER_EOI); start[0] = 0xFF; start[1] = (std_byte) byte_val; if ((byte_val = fetch_non_data_byte(self)) == EOF) return(0); start[2] = (std_byte) byte_val; if ((byte_val = fetch_non_data_byte(self)) == EOF) return(0); start[3] = (std_byte) byte_val; length = start[2]; length <<= 8; length += start[3]; length += 2; /* Length does not include the marker code itself. */ entry = (hpbit_codestream_marker_ptr) local_malloc(HPBIT_MEM_KEY,sizeof(hpbit_codestream_marker)); if (last_entry == NULL) { assert(markers->codestream_markers == NULL); markers->codestream_markers = entry; } else last_entry->next = entry; last_entry = entry; entry->buf = local_malloc(HPBIT_MEM_KEY,length); for (n=0; n < 4; n++) entry->buf[n] = start[n];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -