⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hpbit_stream_out.c

📁 JPEG2000实现的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*****************************************************************************/
/* 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: 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 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".               */
/* Generally, any reference to tile-parts (e.g. through variable names       */
/* containing the string `tpart' are part of this modification, since the    */
/* compressor did not previously need to be tile-part aware.                 */
/* Copyright 2000 The University of New South Wales.                         */
/* All rights reserved for the modified parts.                               */
/*****************************************************************************/

/*****************************************************************************/
/* Modified by Gene Wu to add CRG marker.                                    */
/* 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) {
        /* TJF: Reset remaining_bytes to value at entry to this routine */
        /* TJF: this statement and the one below breaks iterations; not sure
           if it is needed; take out for now
        self->remaining_bytes = num_bytes;  */

        return;
      }
      /* TJF: this statement and the one above breaks iterations; not sure if
         it is needed; take out for now
      self->remaining_bytes = 0; */
    }
  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;
  std_byte id;

  id = ((std_byte *) buf)[1]; /* DST POC mod */
  elt = (hpbit_codestream_marker_ptr)
    local_malloc(HPBIT_MEM_KEY,sizeof(hpbit_codestream_marker));
  elt->instance = instance;
  elt->tpart = 0;
  /* Begin DST POC mod */
  if ((id == (MARKER_POC & 0x00FF)) && (instance > 0))
    {
      elt->tpart = instance - 1;
      elt->instance = 0;
    }
  /* End DST POC mod */
  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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -