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

📄 jdmarker.pas

📁 DELPHI版的JPEG文件解码源程序
💻 PAS
📖 第 1 页 / 共 5 页
字号:
      next_input_byte := datasrc^.next_input_byte;
      bytes_in_buffer := datasrc^.bytes_in_buffer;
    end;
    Dec( bytes_in_buffer );

    b[i] := GETJOCTET(next_input_byte^);
    Inc(next_input_byte);
  end;

  Dec(length, numtoread);

  { process it }
  case (cinfo^.unread_marker) of
  M_APP0:
    examine_app0(cinfo, b, numtoread, length);
  M_APP14:
    examine_app14(cinfo, b, numtoread, length);
  else
    { can't get here unless jpeg_save_markers chooses wrong processor }
    ERREXIT1(j_common_ptr(cinfo), JERR_UNKNOWN_MARKER, cinfo^.unread_marker);
  end;

  { skip any remaining data -- could be lots }

  { Unload the local copies --- do this only at a restart boundary }
  datasrc^.next_input_byte := next_input_byte;
  datasrc^.bytes_in_buffer := bytes_in_buffer;

  if (length > 0) then
    cinfo^.src^.skip_input_data(cinfo, long(length));

  get_interesting_appn := TRUE;
end;

{$ifdef SAVE_MARKERS_SUPPORTED}

{METHODDEF}
function save_marker (cinfo : j_decompress_ptr) : boolean; far;
{ Save an APPn or COM marker into the marker list }
var
  marker : my_marker_ptr;
  cur_marker : jpeg_saved_marker_ptr;
  bytes_read, data_length : uint;
  data : JOCTET_FIELD_PTR;
  length : INT32;
var
  datasrc : jpeg_source_mgr_ptr;
  next_input_byte : JOCTETptr;
  bytes_in_buffer : size_t;
var
  limit : uint;
var
  prev : jpeg_saved_marker_ptr;
begin
  { local copies of input pointer/count }
  datasrc := cinfo^.src;
  next_input_byte := datasrc^.next_input_byte;
  bytes_in_buffer := datasrc^.bytes_in_buffer;

  marker := my_marker_ptr(cinfo^.marker);
  cur_marker := marker^.cur_marker;
  length := 0;

  if (cur_marker = NIL) then
  begin
    { begin reading a marker }
    { Read two bytes interpreted as an unsigned 16-bit integer. }

    { 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
        save_marker := 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
        save_marker := 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 );

    Dec(length, 2);
    if (length >= 0) then
    begin		{ watch out for bogus length word }
      { figure out how much we want to save }

      if (cinfo^.unread_marker = int(M_COM)) then
	limit := marker^.length_limit_COM
      else
	limit := marker^.length_limit_APPn[cinfo^.unread_marker - int(M_APP0)];
      if (uint(length) < limit) then
	limit := uint(length);
      { allocate and initialize the marker item }
      cur_marker := jpeg_saved_marker_ptr(
	cinfo^.mem^.alloc_large (j_common_ptr(cinfo), JPOOL_IMAGE,
                               SIZEOF(jpeg_marker_struct) + limit) );
      cur_marker^.next := NIL;
      cur_marker^.marker := UINT8 (cinfo^.unread_marker);
      cur_marker^.original_length := uint(length);
      cur_marker^.data_length := limit;
      { data area is just beyond the jpeg_marker_struct }
      cur_marker^.data := JOCTET_FIELD_PTR(cur_marker);
      Inc(jpeg_saved_marker_ptr(cur_marker^.data));
      data := cur_marker^.data;

      marker^.cur_marker := cur_marker;
      marker^.bytes_read := 0;
      bytes_read := 0;
      data_length := limit;
    end
    else
    begin
      { deal with bogus length word }
      data_length := 0;
      bytes_read := 0;
      data := NIL;
    end
  end
  else
  begin
    { resume reading a marker }
    bytes_read := marker^.bytes_read;
    data_length := cur_marker^.data_length;
    data := cur_marker^.data;
    Inc(data, bytes_read);
  end;

  while (bytes_read < data_length) do
  begin
    { move the restart point to here }
    datasrc^.next_input_byte := next_input_byte;
    datasrc^.bytes_in_buffer := bytes_in_buffer;

    marker^.bytes_read := bytes_read;
    { If there's not at least one byte in buffer, suspend }
    if (bytes_in_buffer = 0) then
    begin
      if not datasrc^.fill_input_buffer (cinfo) then
      begin
        save_marker := FALSE;
        exit;
      end;
      next_input_byte := datasrc^.next_input_byte;
      bytes_in_buffer := datasrc^.bytes_in_buffer;
    end;

    { Copy bytes with reasonable rapidity }
    while (bytes_read < data_length) and (bytes_in_buffer > 0) do
    begin
      JOCTETPTR(data)^ := next_input_byte^;
      Inc(JOCTETPTR(data));
      Inc(next_input_byte);
      Dec(bytes_in_buffer);
      Inc(bytes_read);
    end;
  end;

  { Done reading what we want to read }
  if (cur_marker <> NIL) then
  begin	{ will be NIL if bogus length word }
    { Add new marker to end of list }
    if (cinfo^.marker_list = NIL) then
    begin
      cinfo^.marker_list := cur_marker
    end
    else
    begin
      prev := cinfo^.marker_list;
      while (prev^.next <> NIL) do
	prev := prev^.next;
      prev^.next := cur_marker;
    end;
    { Reset pointer & calc remaining data length }
    data := cur_marker^.data;
    length := cur_marker^.original_length - data_length;
  end;
  { Reset to initial state for next marker }
  marker^.cur_marker := NIL;

  { Process the marker if interesting; else just make a generic trace msg }
  case (cinfo^.unread_marker) of
  M_APP0:
    examine_app0(cinfo, data^, data_length, length);
  M_APP14:
    examine_app14(cinfo, data^, data_length, length);
  else
    {$IFDEF DEBUG}
    TRACEMS2(j_common_ptr(cinfo), 1, JTRC_MISC_MARKER, cinfo^.unread_marker,
	     int(data_length + length));
    {$ENDIF}
  end;

  { skip any remaining data -- could be lots }
  { do before skip_input_data }
  datasrc^.next_input_byte := next_input_byte;
  datasrc^.bytes_in_buffer := bytes_in_buffer;

  if (length > 0) then
    cinfo^.src^.skip_input_data (cinfo, long(length) );

  save_marker := TRUE;
end;

{$endif} { SAVE_MARKERS_SUPPORTED }


{ Find the next JPEG marker, save it in cinfo^.unread_marker.
  Returns FALSE if had to suspend before reaching a marker;
  in that case cinfo^.unread_marker is unchanged.

  Note that the result might not be a valid marker code,
  but it will never be 0 or FF. }

{LOCAL}
function next_marker (cinfo : j_decompress_ptr) : boolean;
var
  c : int;
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;

  {while TRUE do}
  repeat
    { Read a byte into variable c. 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
        next_marker := 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 );

    c := GETJOCTET(next_input_byte^);
    Inc(next_input_byte);

   { Skip any non-FF bytes.
     This may look a bit inefficient, but it will not occur in a valid file.
     We sync after each discarded byte so that a suspending data source
     can discard the byte from its buffer. }

    while (c <> $FF) do
    begin
      Inc(cinfo^.marker^.discarded_bytes);
      { Unload the local copies --- do this only at a restart boundary }
      datasrc^.next_input_byte := next_input_byte;
      datasrc^.bytes_in_buffer := bytes_in_buffer;

      { Read a byte into variable c. 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
          next_marker := 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 );

      c := GETJOCTET(next_input_byte^);
      Inc(next_input_byte);

    end;
    { This loop swallows any duplicate FF bytes.  Extra FFs are legal as
      pad bytes, so don't count them in discarded_bytes.  We assume there
      will not be so many consecutive FF bytes as to overflow a suspending
      data source's input buffer. }

    repeat
      { Read a byte into variable c. 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
          next_marker := 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 );

      c := GETJOCTET(next_input_byte^);
      Inc(next_input_byte);
    Until (c <> $FF);
    if (c <> 0) then
      break;			{ found a valid marker, exit loop }
    { Reach here if we found a stuffed-zero data sequence (FF/00).
      Discard it and loop back to try again. }

    Inc(cinfo^.marker^.discarded_bytes, 2);
    { Unload the local copies --- do this only at a restart boundary }
    datasrc^.next_input_byte := next_input_byte;
    datasrc^.bytes_in_buffer := bytes_in_buffer;
  Until False;

  if (cinfo^.marker^.discarded_bytes <> 0) then
  begin
    WARNMS2(j_common_ptr(cinfo), JWRN_EXTRANEOUS_DATA,
            cinfo^.marker^.discarded_bytes, c);
    cinfo^.marker^.discarded_bytes := 0;
  end;

  cinfo^.unread_marker := c;

  { Unload the local copies --- do this only at a restart boundary }
  datasrc^.next_input_byte := next_input_byte;
  datasrc^.bytes_in_buffer := bytes_in_buffer;

  next_marker := TRUE;
end;  { next_marker }


{LOCAL}
function first_marker (cinfo : j_decompress_ptr) : boolean;
{ Like next_marker, but used to obtain the initial SOI marker. }
{ For this marker, we do not allow preceding garbage or fill; otherwise,
  we might well scan an entire input file before realizing it ain't JPEG.
  If an application wants to process non-JFIF files, it must seek to the
  SOI before calling the JPEG library. }
var
  c, c2 : int;
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;

  { Read a byte into variable c. 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
      first_marker := 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 );

  c := GETJOCTET(next_input_byte^);
  Inc(next_input_byte);

  { Read a byte into variable c2. 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
      first_marker := 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 );

  c2 := GETJOCTET(next_input_byte^);
  Inc(next_input_byte);

  if (c <> $FF) or (c2 <> int(M_SOI)) then
    ERREXIT2(j_common_ptr(cinfo), JERR_NO_SOI, c, c2);

  cinfo^.unread_marker := c2;

  { Unload the local copies -

⌨️ 快捷键说明

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