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

📄 jdmarker.pas

📁 用pascal寫的jpeg codec, 測試過的
💻 PAS
📖 第 1 页 / 共 5 页
字号:
     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 --- do this only at a restart boundary }
  datasrc^.next_input_byte := next_input_byte;
  datasrc^.bytes_in_buffer := bytes_in_buffer;

  first_marker := TRUE;
end;  { first_marker }


{ Read markers until SOS or EOI.

  Returns same codes as are defined for jpeg_consume_input:
  JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.   }

{METHODDEF}
function read_markers (cinfo : j_decompress_ptr) : int; far;
begin
  { Outer loop repeats once for each marker. }
  repeat
    { Collect the marker proper, unless we already did. }
    { NB: first_marker() enforces the requirement that SOI appear first. }
    if (cinfo^.unread_marker = 0) then
    begin
      if not cinfo^.marker^.saw_SOI then
      begin
        if not first_marker(cinfo) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;
      end
      else
      begin
        if not next_marker(cinfo) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;
      end;
    end;
    { At this point cinfo^.unread_marker contains the marker code and the
      input point is just past the marker proper, but before any parameters.
      A suspension will cause us to return with this state still true. }

    case (cinfo^.unread_marker) of
      M_SOI:
        if not get_soi(cinfo) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      M_SOF0,             { Baseline }
      M_SOF1:             { Extended sequential, Huffman }
        if not get_sof(cinfo, FALSE, FALSE) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;
      M_SOF2:                     { Progressive, Huffman }
        if not get_sof(cinfo, TRUE, FALSE) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      M_SOF9:                     { Extended sequential, arithmetic }
        if not get_sof(cinfo, FALSE, TRUE) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      M_SOF10:                    { Progressive, arithmetic }
        if not get_sof(cinfo, TRUE, TRUE) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      { Currently unsupported SOFn types }
      M_SOF3,                     { Lossless, Huffman }
      M_SOF5,                     { Differential sequential, Huffman }
      M_SOF6,                     { Differential progressive, Huffman }
      M_SOF7,                     { Differential lossless, Huffman }
      M_JPG,                      { Reserved for JPEG extensions }
      M_SOF11,                    { Lossless, arithmetic }
      M_SOF13,                    { Differential sequential, arithmetic }
      M_SOF14,                    { Differential progressive, arithmetic }
      M_SOF15:                    { Differential lossless, arithmetic }
        ERREXIT1(j_common_ptr(cinfo), JERR_SOF_UNSUPPORTED, cinfo^.unread_marker);

      M_SOS:
        begin
          if not get_sos(cinfo) then
          begin
            read_markers := JPEG_SUSPENDED;
            exit;
          end;
          cinfo^.unread_marker := 0;       { processed the marker }
          read_markers := JPEG_REACHED_SOS;
          exit;
        end;

      M_EOI:
        begin
          TRACEMS(j_common_ptr(cinfo), 1, JTRC_EOI);
          cinfo^.unread_marker := 0;       { processed the marker }
          read_markers := JPEG_REACHED_EOI;
          exit;
        end;

      M_DAC:
        if not get_dac(cinfo) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      M_DHT:
        if not get_dht(cinfo) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      M_DQT:
        if not get_dqt(cinfo) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      M_DRI:
        if not get_dri(cinfo) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      M_APP0,
      M_APP1,
      M_APP2,
      M_APP3,
      M_APP4,
      M_APP5,
      M_APP6,
      M_APP7,
      M_APP8,
      M_APP9,
      M_APP10,
      M_APP11,
      M_APP12,
      M_APP13,
      M_APP14,
      M_APP15:
        if not cinfo^.marker^.process_APPn[cinfo^.unread_marker - int(M_APP0)](cinfo) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      M_COM:
        if not cinfo^.marker^.process_COM(cinfo) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      M_RST0,		{ these are all parameterless }
      M_RST1,
      M_RST2,
      M_RST3,
      M_RST4,
      M_RST5,
      M_RST6,
      M_RST7,
      M_TEM:
        TRACEMS1(j_common_ptr(cinfo), 1, JTRC_PARMLESS_MARKER,
          cinfo^.unread_marker);

      M_DNL:		{ Ignore DNL ... perhaps the wrong thing }
        if not skip_variable(cinfo) then
        begin
          read_markers := JPEG_SUSPENDED;
          exit;
        end;

      else			{ must be DHP, EXP, JPGn, or RESn }
        { For now, we treat the reserved markers as fatal errors since they are
          likely to be used to signal incompatible JPEG Part 3 extensions.
          Once the JPEG 3 version-number marker is well defined, this code
          ought to change! }
        ERREXIT1(j_common_ptr(cinfo) , JERR_UNKNOWN_MARKER,
          cinfo^.unread_marker);
    end; { end of case }
    { Successfully processed marker, so reset state variable }
    cinfo^.unread_marker := 0;
  Until false;
end;  { read_markers }


{ Read a restart marker, which is expected to appear next in the datastream;
  if the marker is not there, take appropriate recovery action.
  Returns FALSE if suspension is required.

  This is called by the entropy decoder after it has read an appropriate
  number of MCUs.  cinfo^.unread_marker may be nonzero if the entropy decoder
  has already read a marker from the data source.  Under normal conditions
  cinfo^.unread_marker will be reset to 0 before returning; if not reset,
  it holds a marker which the decoder will be unable to read past. }

{METHODDEF}
function read_restart_marker (cinfo : j_decompress_ptr) :boolean; far;
begin
  { Obtain a marker unless we already did. }
  { Note that next_marker will complain if it skips any data. }
  if (cinfo^.unread_marker = 0) then
  begin
    if not next_marker(cinfo) then
    begin
      read_restart_marker := FALSE;
      exit;
    end;
  end;

  if (cinfo^.unread_marker = (int(M_RST0) + cinfo^.marker^.next_restart_num)) then
  begin
    { Normal case --- swallow the marker and let entropy decoder continue }
    TRACEMS1(j_common_ptr(cinfo), 3, JTRC_RST,
      cinfo^.marker^.next_restart_num);
    cinfo^.unread_marker := 0;
  end
  else
  begin
    { Uh-oh, the restart markers have been messed up. }
    { Let the data source manager determine how to resync. }
    if not cinfo^.src^.resync_to_restart(cinfo,
              cinfo^.marker^.next_restart_num) then
    begin
      read_restart_marker := FALSE;
      exit;
    end;
  end;

  { Update next-restart state }
  with cinfo^.marker^ do
    next_restart_num := (next_restart_num + 1) and 7;

  read_restart_marker := TRUE;
end; { read_restart_marker }


{ This is the default resync_to_restart method for data source managers
  to use if they don't have any better approach.  Some data source managers
  may be able to back up, or may have additional knowledge about the data
  which permits a more intelligent recovery strategy; such managers would
  presumably supply their own resync method.

  read_restart_marker calls resync_to_restart if it finds a marker other than
  the restart marker it was expecting.  (This code is *not* used unless
  a nonzero restart interval has been declared.)  cinfo^.unread_marker is
  the marker code actually found (might be anything, except 0 or FF).
  The desired restart marker number (0..7) is passed as a parameter.
  This routine is supposed to apply whatever error recovery strategy seems
  appropriate in order to position the input stream to the next data segment.
  Note that cinfo^.unread_marker is treated as a marker appearing before
  the current data-source input point; usually it should be reset to zero
  before returning.
  Returns FALSE if suspension is required.

  This implementation is substantially constrained by wanting to treat the
  input as a data stream; this means we can't back up.  Therefore, we have
  only the following actions to work with:
    1. Simply discard the marker and let the entropy decoder resume at next
       byte of file.

⌨️ 快捷键说明

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