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

📄 jdmarker.pas

📁 DELPHI版的JPEG文件解码源程序
💻 PAS
📖 第 1 页 / 共 5 页
字号:
Unit JdMarker;

{ This file contains routines to decode JPEG datastream markers.
  Most of the complexity arises from our desire to support input
  suspension: if not all of the data for a marker is available;
  we must exit back to the application. On resumption; we reprocess
  the marker. }

{ Original: jdmarker.c;  Copyright (C) 1991-1998; Thomas G. Lane. }
{ History
   9.7.96                   Conversion to pascal started      jnn
   22.3.98                  updated to 6b                     jnn }


interface

{$I jconfig.inc}

uses
  jmorecfg,
  jinclude,
  jdeferr,
  jerror,
  jcomapi,
  jpeglib;

const	                { JPEG marker codes }
  M_SOF0  = $c0;
  M_SOF1  = $c1;
  M_SOF2  = $c2;
  M_SOF3  = $c3;
  
  M_SOF5  = $c5;
  M_SOF6  = $c6;
  M_SOF7  = $c7;
  
  M_JPG   = $c8;
  M_SOF9  = $c9;
  M_SOF10 = $ca;
  M_SOF11 = $cb;

  M_SOF13 = $cd;
  M_SOF14 = $ce;
  M_SOF15 = $cf;
  
  M_DHT   = $c4;
  
  M_DAC   = $cc;
  
  M_RST0  = $d0;
  M_RST1  = $d1;
  M_RST2  = $d2;
  M_RST3  = $d3;
  M_RST4  = $d4;
  M_RST5  = $d5;
  M_RST6  = $d6;
  M_RST7  = $d7;
  
  M_SOI   = $d8;
  M_EOI   = $d9;
  M_SOS   = $da;
  M_DQT   = $db;
  M_DNL   = $dc;
  M_DRI   = $dd;
  M_DHP   = $de;
  M_EXP   = $df;
  
  M_APP0  = $e0;
  M_APP1  = $e1;
  M_APP2  = $e2;
  M_APP3  = $e3;
  M_APP4  = $e4;
  M_APP5  = $e5;
  M_APP6  = $e6;
  M_APP7  = $e7;
  M_APP8  = $e8;
  M_APP9  = $e9;
  M_APP10 = $ea;
  M_APP11 = $eb;
  M_APP12 = $ec;
  M_APP13 = $ed;
  M_APP14 = $ee;
  M_APP15 = $ef;
  
  M_JPG0  = $f0;
  M_JPG13 = $fd;
  M_COM   = $fe;

  M_TEM   = $01;

  M_ERROR = $100;

type
  JPEG_MARKER = uint;        { JPEG marker codes }

{ Private state }

type
  my_marker_ptr = ^my_marker_reader;
  my_marker_reader = record
    pub : jpeg_marker_reader; { public fields }

    { Application-overridable marker processing methods }
    process_COM : jpeg_marker_parser_method;
    process_APPn : array[0..16-1] of jpeg_marker_parser_method;

    { Limit on marker data length to save for each marker type }
    length_limit_COM : uint;
    length_limit_APPn : array[0..16-1] of uint;

    { Status of COM/APPn marker saving }
    cur_marker : jpeg_saved_marker_ptr;	{ NIL if not processing a marker }
    bytes_read : uint;		{ data bytes read so far in marker }
    { Note: cur_marker is not linked into marker_list until it's all read. }
  end;

{GLOBAL}
function jpeg_resync_to_restart(cinfo : j_decompress_ptr;
                                desired : int) : boolean;
{GLOBAL}
procedure jinit_marker_reader (cinfo : j_decompress_ptr);

{$ifdef SAVE_MARKERS_SUPPORTED}

{GLOBAL}
procedure jpeg_save_markers (cinfo : j_decompress_ptr;
                             marker_code : int;
		             length_limit : uint);
{$ENDIF}

{GLOBAL}
procedure jpeg_set_marker_processor (cinfo : j_decompress_ptr;
                                     marker_code : int;
	                             routine : jpeg_marker_parser_method);

implementation

uses
  jutils;

{ At all times, cinfo1.src.next_input_byte and .bytes_in_buffer reflect
  the current restart point; we update them only when we have reached a
  suitable place to restart if a suspension occurs. }


{ Routines to process JPEG markers.

  Entry condition: JPEG marker itself has been read and its code saved
    in cinfo^.unread_marker; input restart point is just after the marker.

  Exit: if return TRUE, have read and processed any parameters, and have
    updated the restart point to point after the parameters.
    If return FALSE, was forced to suspend before reaching end of
    marker parameters; restart point has not been moved.  Same routine
    will be called again after application supplies more input data.

  This approach to suspension assumes that all of a marker's parameters
  can fit into a single input bufferload.  This should hold for "normal"
  markers.  Some COM/APPn markers might have large parameter segments
  that might not fit.  If we are simply dropping such a marker, we use
  skip_input_data to get past it, and thereby put the problem on the
  source manager's shoulders.  If we are saving the marker's contents
  into memory, we use a slightly different convention: when forced to
  suspend, the marker processor updates the restart point to the end of
  what it's consumed (ie, the end of the buffer) before returning FALSE.
  On resumption, cinfo->unread_marker still contains the marker code,
  but the data source will point to the next chunk of marker data.
  The marker processor must retain internal state to deal with this.

  Note that we don't bother to avoid duplicate trace messages if a
  suspension occurs within marker parameters.  Other side effects
  require more care. }

{LOCAL}
function get_soi (cinfo : j_decompress_ptr) : boolean;
{ Process an SOI marker }
var
  i : int;
begin
  {$IFDEF DEBUG}
  TRACEMS(j_common_ptr(cinfo), 1, JTRC_SOI);
  {$ENDIF}

  if (cinfo^.marker^.saw_SOI) then
    ERREXIT(j_common_ptr(cinfo), JERR_SOI_DUPLICATE);

  { Reset all parameters that are defined to be reset by SOI }

  for i := 0 to Pred(NUM_ARITH_TBLS) do
  with cinfo^ do
  begin
    arith_dc_L[i] := 0;
    arith_dc_U[i] := 1;
    arith_ac_K[i] := 5;
  end;
  cinfo^.restart_interval := 0;

  { Set initial assumptions for colorspace etc }

  with cinfo^ do
  begin
    jpeg_color_space := JCS_UNKNOWN;
    CCIR601_sampling := FALSE; { Assume non-CCIR sampling??? }

    saw_JFIF_marker := FALSE;
    JFIF_major_version := 1; { set default JFIF APP0 values }
    JFIF_minor_version := 1;
    density_unit := 0;
    X_density := 1;
    Y_density := 1;
    saw_Adobe_marker := FALSE;
    Adobe_transform := 0;

    marker^.saw_SOI := TRUE;
  end;
  get_soi := TRUE;
end; { get_soi }


{LOCAL}
function get_sof(cinfo : j_decompress_ptr;
                 is_prog : boolean;
                 is_arith : boolean) : boolean;
{ Process a SOFn marker }
var
  length : INT32;
  c, ci : int;
  compptr : jpeg_component_info_ptr;
{ Declare and initialize local copies of input pointer/count }
var
  datasrc : jpeg_source_mgr_ptr;
  next_input_byte : JOCTETptr;
  bytes_in_buffer : size_t;
begin
  datasrc := cinfo^.src;
  next_input_byte := datasrc^.next_input_byte;
  bytes_in_buffer := datasrc^.bytes_in_buffer;
{}
  cinfo^.progressive_mode := is_prog;
  cinfo^.arith_code := is_arith;

{ Read two bytes interpreted as an unsigned 16-bit integer.
  length should be declared unsigned int or perhaps INT32. }

{ make a byte available.
  Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
  but we must reload the local copies after a successful fill. }
  if (bytes_in_buffer = 0) then
  begin
    if (not datasrc^.fill_input_buffer(cinfo)) then
    begin
      get_sof := FALSE;
      exit;
    end;
    { Reload the local copies }
    next_input_byte := datasrc^.next_input_byte;
    bytes_in_buffer := datasrc^.bytes_in_buffer;
  end;
  Dec( bytes_in_buffer );

  length := (uint( GETJOCTET(next_input_byte^)) shl 8);
  Inc( next_input_byte );
  { make a byte available.
    Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
    but we must reload the local copies after a successful fill. }
    if (bytes_in_buffer = 0) then
    begin
      if (not datasrc^.fill_input_buffer(cinfo)) then
      begin
        get_sof := FALSE;
        exit;
      end;
      { Reload the local copies }
      next_input_byte := datasrc^.next_input_byte;
      bytes_in_buffer := datasrc^.bytes_in_buffer;
    end;
    Dec( bytes_in_buffer );

  Inc( length, GETJOCTET( next_input_byte^));
  Inc( next_input_byte );


  { Read a byte into variable cinfo^.data_precision.
    If must suspend, return FALSE. }
  { make a byte available.
    Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
    but we must reload the local copies after a successful fill. }
  if (bytes_in_buffer = 0) then
  begin
    if (not datasrc^.fill_input_buffer(cinfo)) then
    begin
      get_sof := FALSE;
      exit;
    end;
    { Reload the local copies }
    next_input_byte := datasrc^.next_input_byte;
    bytes_in_buffer := datasrc^.bytes_in_buffer;
  end;
  Dec( bytes_in_buffer );

  cinfo^.data_precision := GETJOCTET(next_input_byte^);
  Inc(next_input_byte);

{ Read two bytes interpreted as an unsigned 16-bit integer.
  cinfo^.image_height should be declared unsigned int or perhaps INT32. }

{ make a byte available.
  Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
  but we must reload the local copies after a successful fill. }
  if (bytes_in_buffer = 0) then
  begin
    if (not datasrc^.fill_input_buffer(cinfo)) then
    begin
      get_sof := FALSE;
      exit;
    end;
    { Reload the local copies }
    next_input_byte := datasrc^.next_input_byte;
    bytes_in_buffer := datasrc^.bytes_in_buffer;
  end;
  Dec( bytes_in_buffer );

  cinfo^.image_height := (uint( GETJOCTET(next_input_byte^)) shl 8);
  Inc( next_input_byte );
  { make a byte available.
    Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
    but we must reload the local copies after a successful fill. }
    if (bytes_in_buffer = 0) then
    begin
      if (not datasrc^.fill_input_buffer(cinfo)) then
      begin
        get_sof := FALSE;
        exit;
      end;
      { Reload the local copies }
      next_input_byte := datasrc^.next_input_byte;
      bytes_in_buffer := datasrc^.bytes_in_buffer;
    end;
    Dec( bytes_in_buffer );

  Inc( cinfo^.image_height, GETJOCTET( next_input_byte^));
  Inc( next_input_byte );

{ Read two bytes interpreted as an unsigned 16-bit integer.
  cinfo^.image_width should be declared unsigned int or perhaps INT32. }

{ make a byte available.
  Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
  but we must reload the local copies after a successful fill. }
  if (bytes_in_buffer = 0) then
  begin
    if (not datasrc^.fill_input_buffer(cinfo)) then
    begin
      get_sof := FALSE;
      exit;
    end;
    { Reload the local copies }
    next_input_byte := datasrc^.next_input_byte;
    bytes_in_buffer := datasrc^.bytes_in_buffer;
  end;
  Dec( bytes_in_buffer );

  cinfo^.image_width := (uint( GETJOCTET(next_input_byte^)) shl 8);
  Inc( next_input_byte );
  { make a byte available.
    Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
    but we must reload the local copies after a successful fill. }
    if (bytes_in_buffer = 0) then
    begin
      if (not datasrc^.fill_input_buffer(cinfo)) then
      begin
        get_sof := FALSE;
        exit;
      end;
      { Reload the local copies }
      next_input_byte := datasrc^.next_input_byte;
      bytes_in_buffer := datasrc^.bytes_in_buffer;
    end;
    Dec( bytes_in_buffer );

  Inc( cinfo^.image_width, GETJOCTET( next_input_byte^));
  Inc( next_input_byte );

  { Read a byte into variable cinfo^.num_components.
    If must suspend, return FALSE. }
  { make a byte available.
    Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
    but we must reload the local copies after a successful fill. }
  if (bytes_in_buffer = 0) then
  begin
    if (not datasrc^.fill_input_buffer(cinfo)) then
    begin
      get_sof := FALSE;
      exit;
    end;
    { Reload the local copies }
    next_input_byte := datasrc^.next_input_byte;
    bytes_in_buffer := datasrc^.bytes_in_buffer;
  end;
  Dec( bytes_in_buffer );

  cinfo^.num_components := GETJOCTET(next_input_byte^);
  Inc(next_input_byte);

  Dec(length, 8);

  {$IFDEF DEBUG}
  TRACEMS4(j_common_ptr(cinfo), 1, JTRC_SOF, cinfo^.unread_marker,
	   int(cinfo^.image_width), int(cinfo^.image_height),
	   cinfo^.num_components);
  {$ENDIF}

  if (cinfo^.marker^.saw_SOF) then
    ERREXIT(j_common_ptr(cinfo), JERR_SOF_DUPLICATE);

  { We don't support files in which the image height is initially specified }
  { as 0 and is later redefined by DNL.  As long as we have to check that,  }
  { might as well have a general sanity check. }
  if (cinfo^.image_height <= 0) or (cinfo^.image_width <= 0)
      or (cinfo^.num_components <= 0) then
    ERREXIT(j_common_ptr(cinfo), JERR_EMPTY_IMAGE);

  if (length <> (cinfo^.num_components * 3)) then
    ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH);

  if (cinfo^.comp_info = NIL) then { do only once, even if suspend }
    cinfo^.comp_info := jpeg_component_info_list_ptr(

⌨️ 快捷键说明

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