📄 jdmarker.pas
字号:
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-1996; Thomas G. Lane. }
{ History
9.7.96 Conversion to pascal started 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 }
{GLOBAL}
function jpeg_resync_to_restart(cinfo : j_decompress_ptr;
desired : int) : boolean;
{GLOBAL}
procedure jinit_marker_reader (cinfo : j_decompress_ptr);
implementation
uses
jutils;
{ Macro used:
TRACEMS
TRACEMS1
TRACEMS3
ERREXIT
ERREXIT1
WARNMS2
TRACEMS2
GETJOCTET is better defined as a type = byte
The error constants
}
{ 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,
but we use skip_input_data to get past those, and thereby put the problem
on the source manager's shoulders.
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
TRACEMS(j_common_ptr(cinfo), 1, JTRC_SOI);
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;
density_unit := 0; { set default JFIF APP0 values }
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);
TRACEMS4(j_common_ptr(cinfo), 1, JTRC_SOF, cinfo^.unread_marker,
int(cinfo^.image_width), int(cinfo^.image_height),
cinfo^.num_components);
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_ptr(cinfo^.mem^.alloc_small(
j_common_ptr(cinfo), JPOOL_IMAGE,
cinfo^.num_components * SIZEOF(jpeg_component_info)));
compptr := cinfo^.comp_info;
for ci := 0 to pred(cinfo^.num_components) do
begin
compptr^.component_index := ci;
{ Read a byte into variable compptr^.component_id.
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 );
compptr^.component_id := GETJOCTET(next_input_byte^);
Inc(next_input_byte);
{ 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -