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

📄 j2g_fiddle.c

📁 JPEG2000实现的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************/
/* Copyright 2000, Hewlett-Packard Company                                   */
/* All rights reserved                                                       */
/* File: "j2g_fiddle.c"                                                      */
/* Description: Reads and fiddles with JPEG2000 codestreams at a superficial */
/*              level.  Expects a codestream generated using the current     */
/*              version of the VM, with the `-Bresync' and `-Beph' switches  */
/*              enabled.  Provides various facilities for massaging the      */
/*              codestream to test decompressor compliance.  Examples        */
/*              breaking tiles into tile-parts, packing packet heads into    */
/*              PPT/PPM markers, writing pointer markers (PLT, PLM or TLM),  */
/*              reordering tiles, reordering markers within the global       */
/*              or any tile-part header, and stripping in-data and/or        */
/*              pointer markers.  This functionality is expected to          */
/*              be added incrementally.  The program should also eventually  */
/*              include the capability to introduce errors into the          */
/*              for error resilience testing.  Basically, any codestream     */
/*              manipulation which is useful for testing decompressor        */
/*              compliance and functionality, yet which does not affect      */
/*              coding parameters, should be introduced here, rather than    */
/*              in the VM, to avoid cluttering the VM with code which has    */
/*              nothing to do with the compression process itself.           */
/* Author: David Taubman                                                     */
/* Affiliation: Hewlett-Packard and                                          */
/*              The University of New South Wales, Australia                 */
/* Version: VM9.0                                                            */
/* Last Revised: 18 April, 2001                                              */
/*****************************************************************************/

/*****************************************************************************/
/* 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 Gene Wu to add PLT markers option.                            */
/* All changes copyright 2000 by Ricoh Silicon Valley  with all rights       */
/* reserved for the modified parts.                                          */
/*****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ifc.h>
#include <local_services.h>
#include <markers.h>
#include "j2g_fiddle.h"

/*****************************************************************************/
/* STATIC                         complete_marker                            */
/*****************************************************************************/

static j2g_marker_ptr
  complete_marker(std_ushort code, int buf_bytes, std_byte *buf)
{
  j2g_marker_ptr result;

  result = (j2g_marker_ptr) local_malloc("FIDDLE",sizeof(j2g_marker));
  result->marker_code = code;
  result->total_bytes = buf_bytes;
  result->buf = result->buf_handle = (std_byte *)
    local_malloc("FIDDLE",(size_t) buf_bytes);
  result->next = NULL;
  memcpy(result->buf,buf,(size_t) buf_bytes);
  local_free(buf);
  return(result);
}

/*****************************************************************************/
/* STATIC                          read_marker                               */
/*****************************************************************************/

static j2g_marker_ptr
  read_marker(FILE *fp, std_ushort *have_marker_code)

 /* This is the core codestream reading utility.  It reads the next marker
    segment from the codestream.  For most marker segments, the length of the
    segment is available in the two bytes following the marker code itself;
    the only acceptable exceptions currently are: the delimiters: SOC, EOC
    and SOD; and the in-data marker codes SOP and EPH.  EPH markers are entirely
    ignored here.  SOP markers are treated specially, since they have no length
    field, but the segment is assumed to run until the next SOP, SOT or EOC
    marker -- this is how packets are extracted from the codestream.  Due to
    this behaviour, it is possible to read the marker code of the next marker
    segment.  For this reason, the `have_marker_code' argument is used to
    keep track of marker codes which have already been read.  On entry,
    *`have_marker_code' should be 0 or else hold the marker code for the
    marker segment being requested.  On exit, it holds 0 unless we read the
    marker code for an ensuing segment. */

{
  std_byte *buf;
  int max_buf_bytes, buf_bytes;
  int max_length;
  int byte_val;
  int have_ff;
  std_ushort code;

  code = *have_marker_code;
  *have_marker_code = 0;
  if (code == 0)
    {
      byte_val = getc(fp);
      code = (std_ushort) byte_val;
      byte_val = getc(fp);
      code = (code<<8) | (std_ushort) byte_val;
      if (byte_val == EOF)
        local_error("Unexpected end of file!  Your codestream must contain "
                    "the EOC marker!");
    }

  if ((code & 0xFF00) != 0xFF00)
    local_error("Error in codestream: Expected marker code!  Note that "
                "the codestream must contain RESYNC (SOP) markers; use the "
                "VM's `-Bresync' option!");
  buf_bytes = 2;
  max_buf_bytes = 2000; /* A good initial size. */
  buf = (std_byte *) local_malloc("FIDDLE",(size_t) max_buf_bytes);
  buf[0] = (std_byte)((code >> 8) & 0x00FF);
  buf[1] = (std_byte)(code & 0x00FF);
  if ((code == MARKER_SOC) || (code == MARKER_EOC) || (code == MARKER_SOD))
    return(complete_marker(code,buf_bytes,buf));
  if (code == MARKER_EPH)
    local_error("Error in codestream: EPH marker encountered outside packet "
                "head context!");
  buf[2] = (std_byte) getc(fp);
  buf[3] = (std_byte) getc(fp);
  buf_bytes += 2;
  if (code == MARKER_SOP)
    {
      if ((buf[2] != 0) || (buf[3] != 4))
        local_error("Error in codestream: SOP marker must contain a length "
                    "field with the value 4!");
      buf[4] = (std_byte) getc(fp);
      buf[5] = (std_byte) getc(fp);
      buf_bytes += 2;
      max_length = -1;
    }
  else
    {
      max_length = (int) buf[2];
      max_length <<= 8;
      max_length |= (int) buf[3];
      max_length += 2;
      if (max_length < buf_bytes)
        local_error("Invalid marker segment length field!");
    }
  have_ff = 0;
  while (buf_bytes != max_length)
    {
      if (buf_bytes == max_buf_bytes)
        {
          max_buf_bytes += 2000;
          buf = (std_byte *) local_realloc(buf,(size_t) max_buf_bytes);
        }
      byte_val = getc(fp);
      if (byte_val == EOF)
        local_error("Unexpected end of file!  Your codestream must contain "
                    "the EOC marker!");
      buf[buf_bytes++] = (std_byte) byte_val;
      if ((max_length < 0) && have_ff)
        {
          if ((byte_val == (MARKER_SOP & 0x00FF)) ||
              (byte_val == (MARKER_SOT & 0x00FF)) ||
              (byte_val == (MARKER_EOC & 0x00FF)))
            {
              *have_marker_code = 0xFF00 | (std_ushort) byte_val;
              buf_bytes -= 2;
              break;
            }
        }
      have_ff = (byte_val == 0x00FF);
    }
  return(complete_marker(code,buf_bytes,buf));
}

/*****************************************************************************/
/* STATIC                       read_codestream                              */
/*****************************************************************************/

static j2g_codestream_ptr
  read_codestream(FILE *fp)
{
  j2g_codestream_ptr stream;
  j2g_marker_ptr last, marker;
  j2g_tilepart_ptr tp;
  j2g_packet_ptr last_packet, packet;
  std_ushort have_marker_code;

  stream = (j2g_codestream_ptr) local_malloc("FIDDLE",sizeof(j2g_codestream));
  memset(stream,0,sizeof(j2g_codestream));
  have_marker_code = 0;
  last = NULL;
  tp = NULL;
  last_packet = NULL;
  while (((marker = read_marker(fp,&have_marker_code)) != NULL) &&
         (marker->marker_code != MARKER_EOC))
    {
      if ((stream->global_markers == NULL) &&
          (marker->marker_code != MARKER_SOC))
        local_error("Input file does not commence with SOC marker!");
      if (marker->marker_code == MARKER_SOT)
        { /* Start new tile-part. */
          j2g_tilepart_ptr last_tp;

          if (tp == NULL)
            stream->tileparts = tp = (j2g_tilepart_ptr)
              local_malloc("FIDDLE",sizeof(j2g_tilepart));
          else
            tp = tp->next = (j2g_tilepart_ptr)
              local_malloc("FIDDLE",sizeof(j2g_tilepart));
          memset(tp,0,sizeof(j2g_tilepart));
          last = NULL;
          last_packet = NULL;
          tp->tnum = (int) marker->buf[4];
          tp->tnum <<= 8; tp->tnum |= (int) marker->buf[5];
          tp->tpart = (int) marker->buf[10];
          tp->num_tparts = 0;
          if (marker->total_bytes > 11)
            tp->num_tparts = (int) marker->buf[11];
          tp->tile_length = (std_uint) marker->buf[6];
          tp->tile_length <<= 8; tp->tile_length |= (std_uint) marker->buf[7];
          tp->tile_length <<= 8; tp->tile_length |= (std_uint) marker->buf[8];
          tp->tile_length <<= 8; tp->tile_length |= (std_uint) marker->buf[9];
          for (last_tp=stream->tileparts; last_tp != tp; last_tp=last_tp->next)
            if (last_tp->tnum == tp->tnum)
              break;
          if (last_tp == tp)
            {
              tp->uses_eph = stream->global_eph;
              tp->uses_resync = stream->global_resync;
            }
          else
            {
              tp->uses_eph = last_tp->uses_eph;
              tp->uses_resync = last_tp->uses_resync;
            }
          stream->total_tileparts++;
          if (tp->tpart == 0)
            stream->total_tiles++;
        }
      else if ((marker->marker_code == MARKER_PPT) ||
          (marker->marker_code == MARKER_PPM) ||
          (marker->marker_code == MARKER_PLT) ||
          (marker->marker_code == MARKER_PLM))
        local_error("The input codestream may not currently contain any "
                    "of the PPT, PPM, PLT or PLM markers!  These may, "
                    "however, be inserted by the current program!");
      else if (marker->marker_code == MARKER_COD)
        {
          int resync, eph;

          resync = (marker->buf[4] & 2) != 0;
          eph = (marker->buf[4] & 4) != 0;
          if (tp == NULL)
            {
              stream->global_eph = eph;
              stream->global_resync = resync;
            }
          else
            {
              tp->uses_resync = resync;
              tp->uses_eph = eph;
            }
        }
      if (tp == NULL)
        { /* Add to global header. */
          if (last == NULL)
            stream->global_markers = marker;
          else
            last->next = marker;
        }
      else if (marker->marker_code == MARKER_SOP)
        {
          int n, have_ff;

          stream->total_packets++;
          tp->num_packets++;
          packet = (j2g_packet_ptr)
            local_malloc("FIDDLE",sizeof(j2g_packet));
          packet->next = NULL;
          if (last_packet == NULL)
            last_packet = tp->packets = packet;
          else
            last_packet = last_packet->next = packet;
          packet->buf_handle = marker->buf_handle;
          packet->buf = marker->buf;
          packet->packet_bytes = marker->total_bytes;
          packet->head_bytes = 0;
          have_ff = 0;
          for (n=6; n < packet->packet_bytes; n++)
            {
              if (have_ff && (packet->buf[n] == (MARKER_EPH & 0x00FF)))
                {
                  packet->head_bytes = n+1;
                  break;
                }
              have_ff = (packet->buf[n] == 0xFF);
            }
          local_free(marker);
          continue;
        }
      else
        {
          if (last == NULL)
            tp->markers = marker;
          else
            last->next = marker;
        }
      last = marker;
    }

  return(stream);
}

/*****************************************************************************/
/* STATIC                       write_codestream                             */
/*****************************************************************************/

static void
  write_codestream(j2g_codestream_ptr stream, FILE *fp)
{
  j2g_tilepart_ptr tp;
  j2g_marker_ptr marker;
  j2g_packet_ptr packet;
  std_byte eoc[2];

  /* Begin DST SIZ fix. */

  for (marker=stream->global_markers; marker != NULL; marker=marker->next)
    if ((marker->marker_code == MARKER_SOC) ||
        (marker->marker_code == MARKER_SIZ))
      fwrite(marker->buf,1,marker->total_bytes,fp);

  for (marker=stream->global_markers; marker != NULL; marker=marker->next)
    if ((marker->marker_code != MARKER_SIZ) &&
        (marker->marker_code != MARKER_SOC))
      fwrite(marker->buf,1,marker->total_bytes,fp);

  /* End DST SIZ fix. */

  for (tp=stream->tileparts; tp != NULL; tp=tp->next)
    {
      for (marker=tp->markers; marker != NULL; marker=marker->next)
        fwrite(marker->buf,1,marker->total_bytes,fp);
      for (packet=tp->packets; packet != NULL; packet=packet->next)
        fwrite(packet->buf,1,packet->packet_bytes,fp);
    }

⌨️ 快捷键说明

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