📄 jdmarker.pas
字号:
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 + -