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

📄 jdphuff.pas

📁 用pascal寫的jpeg codec, 測試過的
💻 PAS
📖 第 1 页 / 共 3 页
字号:
Unit JdpHuff;

{ This file contains Huffman entropy decoding routines for progressive JPEG.

  Much of the complexity here has to do with supporting input suspension.
  If the data source module demands suspension, we want to be able to back
  up to the start of the current MCU.  To do this, we copy state variables
  into local working storage, and update them back to the permanent
  storage only upon successful completion of an MCU. }

{ Original: jdphuff.c ; Copyright (C) 1995-1996, Thomas G. Lane. }

interface

{$I jconfig.inc}

uses
  jmorecfg,
  jinclude,
  jpeglib,
  jdeferr,
  jerror,
  jutils,
  jdhuff;		{ Declarations shared with jdhuff.c }


{GLOBAL}
procedure jinit_phuff_decoder (cinfo : j_decompress_ptr);

implementation

{ Expanded entropy decoder object for progressive Huffman decoding.

  The savable_state subrecord contains fields that change within an MCU,
  but must not be updated permanently until we complete the MCU. }

type
  savable_state = record
    EOBRUN : uInt;               { remaining EOBs in EOBRUN }
    last_dc_val : array[00..MAX_COMPS_IN_SCAN-1] of int;
                                 { last DC coef for each component }
  end;


type
  phuff_entropy_ptr  = ^phuff_entropy_decoder;
  phuff_entropy_decoder = record
    pub : jpeg_entropy_decoder; { public fields }

    { These fields are loaded into local variables at start of each MCU.
      In case of suspension, we exit WITHOUT updating them. }

    bitstate : bitread_perm_state;	{ Bit buffer at start of MCU }
    saved : savable_state;		{ Other state at start of MCU }

    { These fields are NOT loaded into local working state. }
    restarts_to_go : uInt;              { MCUs left in this restart interval }

    { Pointers to derived tables (these workspaces have image lifespan) }
    derived_tbls : array[0..NUM_HUFF_TBLS-1] of d_derived_tbl_ptr;

    ac_derived_tbl : d_derived_tbl_ptr; { active table during an AC scan }
  end;



{ Forward declarations }
{METHODDEF}
function decode_mcu_DC_first (cinfo : j_decompress_ptr;
                              var MCU_data : array of JBLOCKROW) : boolean;
                              far; forward;
{METHODDEF}
function decode_mcu_AC_first (cinfo : j_decompress_ptr;
                              var MCU_data : array of JBLOCKROW) : boolean;
                              far; forward;
{METHODDEF}
function decode_mcu_DC_refine (cinfo : j_decompress_ptr;
                               var MCU_data : array of JBLOCKROW) : boolean;
                               far; forward;
{METHODDEF}
function decode_mcu_AC_refine (cinfo : j_decompress_ptr;
                               var MCU_data : array of JBLOCKROW) : boolean;
                               far; forward;

{ Initialize for a Huffman-compressed scan. }

{METHODDEF}
procedure start_pass_phuff_decoder (cinfo : j_decompress_ptr); far;
var
  entropy : phuff_entropy_ptr;
  is_DC_band, bad : boolean;
  ci, coefi, tbl : int;
  coef_bit_ptr : coef_bits_ptr;
  compptr : jpeg_component_info_ptr;
var
  cindex : int;
  expected : int;
begin
  entropy := phuff_entropy_ptr (cinfo^.entropy);

  is_DC_band := (cinfo^.Ss = 0);

  { Validate scan parameters }
  bad := FALSE;
  if (is_DC_band) then
  begin
    if (cinfo^.Se <> 0) then
      bad := TRUE;
  end
  else
  begin
    { need not check Ss/Se < 0 since they came from unsigned bytes }
    if (cinfo^.Ss > cinfo^.Se) or (cinfo^.Se >= DCTSIZE2) then
      bad := TRUE;
    { AC scans may have only one component }
    if (cinfo^.comps_in_scan <> 1) then
      bad := TRUE;
  end;
  if (cinfo^.Ah <> 0) then
  begin
    { Successive approximation refinement scan: must have Al = Ah-1. }
    if (cinfo^.Al <> cinfo^.Ah-1) then
      bad := TRUE;
  end;
  if (cinfo^.Al > 13) then      { need not check for < 0 }
    bad := TRUE;
  if (bad) then
    ERREXIT4(j_common_ptr(cinfo), JERR_BAD_PROGRESSION,
	     cinfo^.Ss, cinfo^.Se, cinfo^.Ah, cinfo^.Al);
  { Update progression status, and verify that scan order is legal.
    Note that inter-scan inconsistencies are treated as warnings
    not fatal errors ... not clear if this is right way to behave. }

  for ci := 0 to pred(cinfo^.comps_in_scan) do
  begin
    cindex := cinfo^.cur_comp_info[ci]^.component_index;
    coef_bit_ptr := coef_bits_ptr(@(cinfo^.coef_bits^[cindex])); {^[0] ???
                                                                   Nomssi    }
    if (not is_DC_band) and (coef_bit_ptr^[0] < 0) then
      { AC without prior DC scan }
      WARNMS2(j_common_ptr(cinfo), JWRN_BOGUS_PROGRESSION, cindex, 0);
    for coefi := cinfo^.Ss to cinfo^.Se do
    begin
      if (coef_bit_ptr^[coefi] < 0) then
        expected :=  0
      else
        expected := coef_bit_ptr^[coefi];
      if (cinfo^.Ah <> expected) then
	WARNMS2(j_common_ptr(cinfo), JWRN_BOGUS_PROGRESSION, cindex, coefi);
      coef_bit_ptr^[coefi] := cinfo^.Al;
    end;
  end;

  { Select MCU decoding routine }
  if (cinfo^.Ah = 0) then
  begin
    if (is_DC_band) then
      entropy^.pub.decode_mcu := decode_mcu_DC_first
    else
      entropy^.pub.decode_mcu := decode_mcu_AC_first;
  end
  else
  begin
    if (is_DC_band) then
      entropy^.pub.decode_mcu := decode_mcu_DC_refine
    else
      entropy^.pub.decode_mcu := decode_mcu_AC_refine;
  end;

  for ci := 0 to pred(cinfo^.comps_in_scan) do
  begin
    compptr := cinfo^.cur_comp_info[ci];
    { Make sure requested tables are present, and compute derived tables.
      We may build same derived table more than once, but it's not expensive. }

    if (is_DC_band) then
    begin
      if (cinfo^.Ah = 0) then
      begin	{ DC refinement needs no table }
	tbl := compptr^.dc_tbl_no;
	if (tbl < 0) or (tbl >= NUM_HUFF_TBLS) or
	   (cinfo^.dc_huff_tbl_ptrs[tbl] = NIL) then
	  ERREXIT1(j_common_ptr(cinfo), JERR_NO_HUFF_TABLE, tbl);
	jpeg_make_d_derived_tbl(cinfo, cinfo^.dc_huff_tbl_ptrs[tbl],
				 entropy^.derived_tbls[tbl]);
      end;
    end
    else
    begin
      tbl := compptr^.ac_tbl_no;
      if (tbl < 0) or (tbl >= NUM_HUFF_TBLS) or
         (cinfo^.ac_huff_tbl_ptrs[tbl] = NIL) then
        ERREXIT1(j_common_ptr(cinfo), JERR_NO_HUFF_TABLE, tbl);
      jpeg_make_d_derived_tbl(cinfo, cinfo^.ac_huff_tbl_ptrs[tbl],
			       entropy^.derived_tbls[tbl]);
      { remember the single active table }
      entropy^.ac_derived_tbl := entropy^.derived_tbls[tbl];
    end;
    { Initialize DC predictions to 0 }
    entropy^.saved.last_dc_val[ci] := 0;
  end;

  { Initialize bitread state variables }
  entropy^.bitstate.bits_left := 0;
  entropy^.bitstate.get_buffer := 0; { unnecessary, but keeps Purify quiet }
  entropy^.bitstate.printed_eod := FALSE;

  { Initialize private state variables }
  entropy^.saved.EOBRUN := 0;

  { Initialize restart counter }
  entropy^.restarts_to_go := cinfo^.restart_interval;
end;


{ Figure F.12: extend sign bit.
  On some machines, a shift and add will be faster than a table lookup. }

{$ifdef AVOID_TABLES}

#define HUFF_EXTEND(x,s)
  ((x) < (1shl((s)-1)) ? (x) + (((-1)shl(s)) + 1) : (x))

{$else}

{ #define HUFF_EXTEND(x,s)
  if (x) < extend_test[s] then
    (x) + extend_offset[s]
  else
    (x)}

const
 extend_test : Array[0..16-1] of int =   { entry n is 2**(n-1) }
   ($0000, $0001, $0002, $0004, $0008, $0010, $0020, $0040,
    $0080, $0100, $0200, $0400, $0800, $1000, $2000, $4000);

const
  extend_offset : array[0..16-1] of int = { entry n is (-1 shl n) + 1 }
  ( 0, ((-1) shl 1) + 1, ((-1) shl 2) + 1, ((-1) shl 3) + 1, ((-1) shl 4) + 1,
    ((-1) shl 5) + 1, ((-1) shl 6) + 1, ((-1) shl 7) + 1, ((-1) shl 8) + 1,
    ((-1) shl 9) + 1, ((-1) shl 10) + 1, ((-1) shl 11) + 1, ((-1) shl 12) + 1,
    ((-1) shl 13) + 1, ((-1) shl 14) + 1, ((-1) shl 15) + 1 );

{$endif} { AVOID_TABLES }


{ Check for a restart marker & resynchronize decoder.
  return:=s FALSE if must suspend. }

{LOCAL}
function process_restart (cinfo : j_decompress_ptr) : boolean;
var
  entropy : phuff_entropy_ptr; 
  ci : int;
begin
  entropy := phuff_entropy_ptr (cinfo^.entropy);

  { Throw away any unused bits remaining in bit buffer; }
  { include any full bytes in next_marker's count of discarded bytes }
  Inc(cinfo^.marker^.discarded_bytes, entropy^.bitstate.bits_left div 8);
  entropy^.bitstate.bits_left := 0;

  { Advance past the RSTn marker }
  if (not cinfo^.marker^.read_restart_marker (cinfo)) then
  begin
    process_restart := FALSE;
    exit;
  end;

  { Re-initialize DC predictions to 0 }
  for ci := 0 to pred(cinfo^.comps_in_scan) do
    entropy^.saved.last_dc_val[ci] := 0;
  { Re-init EOB run count, too }
  entropy^.saved.EOBRUN := 0;

  { Reset restart counter }
  entropy^.restarts_to_go := cinfo^.restart_interval;

  { Next segment can get another out-of-data warning }
  entropy^.bitstate.printed_eod := FALSE;

  process_restart := TRUE;
end;


{ Huffman MCU decoding.
  Each of these routines decodes and return:=s one MCU's worth of
  Huffman-compressed coefficients.
  The coefficients are reordered from zigzag order into natural array order,
  but are not dequantized.

  The i'th block of the MCU is stored into the block pointed to by
  MCU_data[i].  WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.

  We return:= FALSE if data source requested suspension.  In that case no
  changes have been made to permanent state.  (Exception: some output
  coefficients may already have been assigned.  This is harmless for
  spectral selection, since we'll just re-assign them on the next call.
  Successive approximation AC refinement has to be more careful, however.) }


{ MCU decoding for DC initial scan (either spectral selection,
  or first pass of successive approximation). }

{METHODDEF}
function decode_mcu_DC_first (cinfo : j_decompress_ptr;
                              var MCU_data : array of JBLOCKROW) : boolean;
label
  label1;
var
  entropy : phuff_entropy_ptr;
  Al : int;
  {register} s, r : int;
  blkn, ci : int;
  block : JBLOCK_PTR;
  {BITREAD_STATE_VARS;}
  get_buffer : bit_buf_type ; {register}
  bits_left : int; {register}
  br_state : bitread_working_state;

  state : savable_state;
  tbl : d_derived_tbl_ptr;
  compptr : jpeg_component_info_ptr;
var
  nb, look : int; {register}
begin
  entropy := phuff_entropy_ptr (cinfo^.entropy);
  Al := cinfo^.Al;

  { Process restart marker if needed; may have to suspend }
  if (cinfo^.restart_interval <> 0) then
  begin
    if (entropy^.restarts_to_go = 0) then
      if (not process_restart(cinfo)) then
      begin
	decode_mcu_DC_first := FALSE;
        exit;
      end;
  end;

  { Load up working state }
  {BITREAD_LOAD_STATE(cinfo,entropy^.bitstate);}
  br_state.cinfo := cinfo;
  br_state.next_input_byte := cinfo^.src^.next_input_byte;
  br_state.bytes_in_buffer := cinfo^.src^.bytes_in_buffer;
  br_state.unread_marker := cinfo^.unread_marker;
  get_buffer := entropy^.bitstate.get_buffer;
  bits_left := entropy^.bitstate.bits_left;
  br_state.printed_eod_ptr := @entropy^.bitstate.printed_eod;

⌨️ 快捷键说明

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