📄 hpbit_stream_out.c
字号:
/*****************************************************************************//* Copyright 1998, Hewlett-Packard Company *//* All rights reserved *//* File: "hpbit_stream_out.c" *//* Description: Reference implementation of the `stream_out' 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: 25 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 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 <string.h>#include <assert.h>#include <ifc.h>#include <markers.h>#include "hpbit_stream_out_local.h"#include "hpbit_markers.h"/* ========================================================================= *//* ---------------------------- Internal Functions ------------------------- *//* ========================================================================= *//*****************************************************************************//* STATIC make_big_endian *//*****************************************************************************/static void make_big_endian(void *buf, int num_words, int precision) /* Use this convenience function to reverse the byte order in words from which a buffer is constructed, when the current architecture uses a Little Endian byte order. The `buf' argument is assumed to point to a structure consisting of integer-valued fields with 1, 2 or 4 bytes of precision each. */{ int bigendian, n; std_byte *bp, b0, b1, b2, b3; bigendian = 1; bp = (std_byte *)(&bigendian); *bp = 0; if (bigendian || (precision == 1)) return; assert(num_words != 0); if (precision == 2) { for (bp=(std_byte *) buf, n=num_words; n > 0; n--, bp += 2) { b0 = bp[0]; b1 = bp[1]; bp[0] = b1; bp[1] = b0; } } else if (precision == 4) { for (bp=(std_byte *) buf, n=num_words; n > 0; n--, bp += 4) { b0 = bp[0]; b1 = bp[1]; b2 = bp[2]; b3 = bp[3]; bp[0] = b3; bp[1] = b2; bp[2] = b1; bp[3] = b0; } } else assert(0);}/*****************************************************************************//* STATIC copy_to_big_endian *//*****************************************************************************/static void copy_to_big_endian(void *src, void *dst, int num_words, int precision) /* Copies the `src' data to the `dst' data and performs any byte reversal required to ensure that quantities represented in `dst' have the Big Endian byte order. */{ 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 emit_bytes *//*****************************************************************************/static void emit_bytes(hpbit_stream_out_ref self, std_byte *buf, int num_bytes) /* Emits the indicated bytes directly to the file, up to the limit imposed by `self->remaining_bytes'. Byte stuffing, error correction codes, etc., should all be handled at a higher level by functions which ultimately call this function to output the final code stream. */{ self->remaining_bytes -= num_bytes; if (self->remaining_bytes < 0) { num_bytes += self->remaining_bytes; if (num_bytes <= 0) return; } fwrite(buf,1,(size_t) num_bytes,self->fp);}/*****************************************************************************//* STATIC emit_words *//*****************************************************************************/static void emit_words(hpbit_stream_out_ref self, void *buf, int num_words, int precision) /* Same as `emit_bytes' except that the function emits multi-byte values. `precision' indicates the number of bytes in each word; it must be one of 1, 2 or 4. The function differs from `emit_bytes' in that it may reorganize the bytes in each word to achieve a consistent BIGENDIAN byte order (MSB first). */{ make_big_endian(buf,num_words,precision); emit_bytes(self,(std_byte *) buf,precision*num_words);}/*****************************************************************************//* STATIC add_tile *//*****************************************************************************/static hpbit_tile_ptr add_tile(hpbit_stream_out_ref self, int tnum){ hpbit_tile_ptr tile; tile = (hpbit_tile_ptr) local_malloc(HPBIT_MEM_KEY,sizeof(hpbit_tile)); tile->tnum = tnum; tile->next = self->tiles; self->tiles = tile; tile->resync = self->global_resync; tile->eph = self->global_eph; return(tile);}/*****************************************************************************//* STATIC insert_pre_marker_element *//*****************************************************************************/static void insert_pre_marker_element(hpbit_marker_elt_ptr elt, hpbit_pre_marker_ptr pm) /* Inserts the new element into the list of elements managed by the `pm' structure, being careful to apply a unique ordering condition to the marker elements to facilitate later comparison of markers. */{ hpbit_marker_elt_ptr scan, last; for (last=NULL, scan=pm->elements; scan != NULL; last=scan, scan=scan->next) if (scan->element_id > elt->element_id) break; elt->next = scan; if (last == NULL) pm->elements = elt; else last->next = elt;}/*****************************************************************************//* 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); if (elt->set_buf != NULL) local_free(elt->set_buf); local_free(elt); } local_free(pm);}/*****************************************************************************//* STATIC link_connected_pre_markers *//*****************************************************************************/static void link_connected_pre_markers(hpbit_markers_ptr markers) /* This function implements any prior knowledge concerning the inter-dependence of pre-markers. The main objective is to ensure that a marker will be eliminated (as redundant) from a tile-header only if all dependent markers in the tile-header can simultaneously be eliminated. */{ hpbit_pre_marker_ptr pm, prev; /* Process connectedness of COD/COC markers. */ for (prev=NULL, pm=markers->pre_markers; pm != NULL; pm = pm->next) if ((pm->id == (MARKER_COD & 0x00FF)) || (pm->id == (MARKER_COC & 0x00FF))) { pm->link_prev = prev; if (prev != NULL) prev->link_next = pm; prev = pm; } /* Process connectedness of QCD/QCC markers. */ for (prev=NULL, pm=markers->pre_markers; pm != NULL; pm = pm->next) if ((pm->id == (MARKER_QCD & 0x00FF)) || (pm->id == (MARKER_QCC & 0x00FF))) { pm->link_prev = prev; if (prev != NULL) prev->link_next = pm; prev = pm; }}/*****************************************************************************//* STATIC add_codestream_marker *//*****************************************************************************/static void add_codestream_marker(hpbit_markers_ptr markers, void *buf, int length, int instance, int place_at_end) /* Use this convenience function to push newly created codestream markers onto the list (LIFO) referenced from a `markers' structure (there is one `markers' structure for the global header and one for each tile header. The contents of the `buf' array are already supposed to contain values with the correct byte alignment (i.e. big endian). The `place_at_end' argument indicates whether the new marker should be placed at the end or the front of the current list of codestream markers. This should be irrelevant for all markers except the CME marker, which is the only one for which order of appearance in the codestream has some significance (if there are multiple occurrences of the same marker with the same Rcme value). */{ hpbit_codestream_marker_ptr elt, last; elt = (hpbit_codestream_marker_ptr) local_malloc(HPBIT_MEM_KEY,sizeof(hpbit_codestream_marker)); elt->instance = instance; elt->num_bytes = length; elt->buf = buf; last = markers->codestream_markers; if (place_at_end && (last != NULL)) { while (last->next != NULL) last = last->next; last->next = elt; } else { elt->next = markers->codestream_markers; markers->codestream_markers = elt; } markers->total_codestream_bytes += elt->num_bytes;}/*****************************************************************************//* STATIC get_tile_component_bands *//*****************************************************************************/static int get_tile_component_bands(hpbit_stream_out_ref self, int tnum, int comp_idx, int num_levels) /* This function computes the total number of bands for the relevant tile-component based on the number of decomposition levels and any special decomposition structure. */{ int length, hp_descent, num_bands, n; length = (int) self->base.size_marker_elt(&(self->base),tnum,MARKER_COC_DECOMP,comp_idx); if (length == 0) return(3*num_levels+1); /* Mallat decomposition. */ num_bands = 1; hp_descent = 0; for (n=0; n < num_levels; n++) { if (n < length) hp_descent = (int) self->base.get_marker_val(&(self->base),tnum,MARKER_COC_DECOMP, comp_idx,n); if (hp_descent == 1) num_bands += 3; else if (hp_descent == 2) num_bands += 12; else if (hp_descent == 3) num_bands += 48; else num_bands += 3; /* Error; use Mallat as default. */ } return(num_bands);}/*****************************************************************************//* STATIC translate_cod_coc_markers */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -