1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644 |
- 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(
- cinfo^.mem^.alloc_small(j_common_ptr(cinfo), JPOOL_IMAGE,
- cinfo^.num_components * SIZEOF(jpeg_component_info)));
- compptr := jpeg_component_info_ptr(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
- 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 );
- c := GETJOCTET(next_input_byte^);
- Inc(next_input_byte);
- compptr^.h_samp_factor := (c shr 4) and 15;
- compptr^.v_samp_factor := (c ) and 15;
- { Read a byte into variable compptr^.quant_tbl_no.
- 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^.quant_tbl_no := GETJOCTET(next_input_byte^);
- Inc(next_input_byte);
- {$IFDEF DEBUG}
- TRACEMS4(j_common_ptr(cinfo), 1, JTRC_SOF_COMPONENT,
- compptr^.component_id, compptr^.h_samp_factor,
- compptr^.v_samp_factor, compptr^.quant_tbl_no);
- {$ENDIF}
- Inc(compptr);
- end;
- cinfo^.marker^.saw_SOF := TRUE;
- { 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;
- get_sof := TRUE;
- end; { get_sof }
- {LOCAL}
- function get_sos (cinfo : j_decompress_ptr) : boolean;
- { Process a SOS marker }
- label
- id_found;
- var
- length : INT32;
- i, ci, n, c, cc : 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; { Array[] of JOCTET; }
- bytes_in_buffer : size_t;
- begin
- datasrc := cinfo^.src;
- next_input_byte := datasrc^.next_input_byte;
- bytes_in_buffer := datasrc^.bytes_in_buffer;
- {}
- if not cinfo^.marker^.saw_SOF then
- ERREXIT(j_common_ptr(cinfo), JERR_SOS_NO_SOF);
- { 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_sos := 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_sos := 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 n (Number of 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_sos := 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 );
- n := GETJOCTET(next_input_byte^); { Number of components }
- Inc(next_input_byte);
- {$IFDEF DEBUG}
- TRACEMS1(j_common_ptr(cinfo), 1, JTRC_SOS, n);
- {$ENDIF}
- if ((length <> (n * 2 + 6)) or (n < 1) or (n > MAX_COMPS_IN_SCAN)) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH);
- cinfo^.comps_in_scan := n;
- { Collect the component-spec parameters }
- for i := 0 to Pred(n) do
- begin
- { Read a byte into variable cc. 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_sos := 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 );
- cc := 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
- if (not datasrc^.fill_input_buffer(cinfo)) then
- begin
- get_sos := 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);
- compptr := jpeg_component_info_ptr(cinfo^.comp_info);
- for ci := 0 to Pred(cinfo^.num_components) do
- begin
- if (cc = compptr^.component_id) then
- goto id_found;
- Inc(compptr);
- end;
- ERREXIT1(j_common_ptr(cinfo), JERR_BAD_COMPONENT_ID, cc);
- id_found:
- cinfo^.cur_comp_info[i] := compptr;
- compptr^.dc_tbl_no := (c shr 4) and 15;
- compptr^.ac_tbl_no := (c ) and 15;
- {$IFDEF DEBUG}
- TRACEMS3(j_common_ptr(cinfo), 1, JTRC_SOS_COMPONENT, cc,
- compptr^.dc_tbl_no, compptr^.ac_tbl_no);
- {$ENDIF}
- end;
- { Collect the additional scan parameters Ss, Se, Ah/Al. }
- { 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
- get_sos := 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);
- cinfo^.Ss := c;
- { 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
- get_sos := 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);
- cinfo^.Se := c;
- { 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
- get_sos := 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);
- cinfo^.Ah := (c shr 4) and 15;
- cinfo^.Al := (c ) and 15;
- {$IFDEF DEBUG}
- TRACEMS4(j_common_ptr(cinfo), 1, JTRC_SOS_PARAMS, cinfo^.Ss, cinfo^.Se,
- cinfo^.Ah, cinfo^.Al);
- {$ENDIF}
- { Prepare to scan data & restart markers }
- cinfo^.marker^.next_restart_num := 0;
- { Count another SOS marker }
- Inc( cinfo^.input_scan_number );
- { 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;
- get_sos := TRUE;
- end; { get_sos }
- {METHODDEF}
- function skip_variable (cinfo : j_decompress_ptr) : boolean; far;
- { Skip over an unknown or uninteresting variable-length marker }
- var
- length : INT32;
- var
- datasrc : jpeg_source_mgr_ptr;
- next_input_byte : JOCTETptr; { Array[] of JOCTET; }
- bytes_in_buffer : size_t;
- begin
- datasrc := cinfo^.src;
- next_input_byte := datasrc^.next_input_byte;
- bytes_in_buffer := datasrc^.bytes_in_buffer;
- { 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
- skip_variable := 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
- skip_variable := 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);
- {$IFDEF DEBUG}
- TRACEMS2(j_common_ptr(cinfo), 1, JTRC_MISC_MARKER,
- cinfo^.unread_marker, int(length));
- {$ENDIF}
- { Unload the local copies --- do this only at a restart boundary }
- { 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));
- skip_variable := TRUE;
- end; { skip_variable }
- {$IFDEF D_ARITH_CODING_SUPPORTED}
- {LOCAL}
- function get_dac (cinfo : j_decompress_ptr) : boolean;
- { Process a DAC marker }
- var
- length : INT32;
- index, val : 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 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_dac := 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_dac := 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);
- while (length > 0) do
- begin
- { Read a byte into variable index. 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_dac := 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 );
- index := GETJOCTET(next_input_byte^);
- Inc(next_input_byte);
- { Read a byte into variable val. 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_dac := 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 );
- val := GETJOCTET(next_input_byte^);
- Inc(next_input_byte);
- Dec( length, 2);
- {$IFDEF DEBUG}
- TRACEMS2(j_common_ptr(cinfo), 1, JTRC_DAC, index, val);
- {$ENDIF}
- if (index < 0) or (index >= (2*NUM_ARITH_TBLS)) then
- ERREXIT1(j_common_ptr(cinfo) , JERR_DAC_INDEX, index);
- if (index >= NUM_ARITH_TBLS) then
- begin { define AC table }
- cinfo^.arith_ac_K[index-NUM_ARITH_TBLS] := UINT8(val);
- end
- else
- begin { define DC table }
- cinfo^.arith_dc_L[index] := UINT8(val and $0F);
- cinfo^.arith_dc_U[index] := UINT8(val shr 4);
- if (cinfo^.arith_dc_L[index] > cinfo^.arith_dc_U[index]) then
- ERREXIT1(j_common_ptr(cinfo) , JERR_DAC_VALUE, val);
- end;
- end;
- if (length <> 0) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH);
- { 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;
- get_dac := TRUE;
- end; { get_dac }
- {$ELSE}
- {LOCAL}
- function get_dac (cinfo : j_decompress_ptr) : boolean;
- begin
- get_dac := skip_variable(cinfo);
- end;
- {$ENDIF}
- {LOCAL}
- function get_dht (cinfo : j_decompress_ptr) : boolean;
- { Process a DHT marker }
- var
- length : INT32;
- bits : Array[0..17-1] of UINT8;
- huffval : Array[0..256-1] of UINT8;
- i, index, count : int;
- htblptr : ^JHUFF_TBL_PTR;
- 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 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_dht := 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_dht := 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);
- while (length > 16) do
- begin
- { Read a byte into variable index. 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_dht := 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 );
- index := GETJOCTET(next_input_byte^);
- Inc(next_input_byte);
- {$IFDEF DEBUG}
- TRACEMS1(j_common_ptr(cinfo), 1, JTRC_DHT, index);
- {$ENDIF}
- bits[0] := 0;
- count := 0;
- for i := 1 to 16 do
- begin
- { Read a byte into variable bits[i]. 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_dht := 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 );
- bits[i] := GETJOCTET(next_input_byte^);
- Inc(next_input_byte);
- Inc( count, bits[i] );
- end;
- Dec( length, (1 + 16) );
- {$IFDEF DEBUG}
- TRACEMS8(j_common_ptr(cinfo), 2, JTRC_HUFFBITS,
- bits[1], bits[2], bits[3], bits[4],
- bits[5], bits[6], bits[7], bits[8]);
- TRACEMS8(j_common_ptr(cinfo), 2, JTRC_HUFFBITS,
- bits[9], bits[10], bits[11], bits[12],
- bits[13], bits[14], bits[15], bits[16]);
- {$ENDIF}
- { Here we just do minimal validation of the counts to avoid walking
- off the end of our table space. jdhuff.c will check more carefully. }
- if (count > 256) or (INT32(count) > length) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_HUFF_TABLE);
- for i := 0 to Pred(count) do
- begin
- { Read a byte into variable huffval[i]. 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_dht := 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 );
- huffval[i] := GETJOCTET(next_input_byte^);
- Inc(next_input_byte);
- end;
- Dec( length, count );
- if (index and $10)<>0 then
- begin { AC table definition }
- Dec( index, $10 );
- htblptr := @cinfo^.ac_huff_tbl_ptrs[index];
- end
- else
- begin { DC table definition }
- htblptr := @cinfo^.dc_huff_tbl_ptrs[index];
- end;
- if (index < 0) or (index >= NUM_HUFF_TBLS) then
- ERREXIT1(j_common_ptr(cinfo), JERR_DHT_INDEX, index);
- if (htblptr^ = NIL) then
- htblptr^ := jpeg_alloc_huff_table(j_common_ptr(cinfo));
- MEMCOPY(@(htblptr^)^.bits, @bits, SIZEOF((htblptr^)^.bits));
- MEMCOPY(@(htblptr^)^.huffval, @huffval, SIZEOF((htblptr^)^.huffval));
- end;
- if (length <> 0) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH);
- { 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;
- get_dht := TRUE;
- end; { get_dht }
- {LOCAL}
- function get_dqt (cinfo : j_decompress_ptr) : boolean;
- { Process a DQT marker }
- var
- length : INT32;
- n, i, prec : int;
- tmp : uint;
- quant_ptr : JQUANT_TBL_PTR;
- 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 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_dqt := 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_dqt := 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 );
- while (length > 0) do
- begin
- { Read a byte into variable n. 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_dqt := 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 );
- n := GETJOCTET(next_input_byte^);
- Inc(next_input_byte);
- prec := n shr 4;
- n := n and $0F;
- {$IFDEF DEBUG}
- TRACEMS2(j_common_ptr(cinfo), 1, JTRC_DQT, n, prec);
- {$ENDIF}
- if (n >= NUM_QUANT_TBLS) then
- ERREXIT1(j_common_ptr(cinfo) , JERR_DQT_INDEX, n);
- if (cinfo^.quant_tbl_ptrs[n] = NIL) then
- cinfo^.quant_tbl_ptrs[n] := jpeg_alloc_quant_table(j_common_ptr(cinfo));
- quant_ptr := cinfo^.quant_tbl_ptrs[n];
- for i := 0 to Pred(DCTSIZE2) do
- begin
- if (prec <> 0) then
- begin
- { Read two bytes interpreted as an unsigned 16-bit integer.
- tmp 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_dqt := 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 );
- tmp := (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_dqt := 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( tmp, GETJOCTET( next_input_byte^));
- Inc( next_input_byte );
- end
- else
- begin
- { Read a byte into variable tmp. 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_dqt := 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 );
- tmp := GETJOCTET(next_input_byte^);
- Inc(next_input_byte);
- end;
- { We convert the zigzag-order table to natural array order. }
- quant_ptr^.quantval[jpeg_natural_order[i]] := UINT16(tmp);
- end;
- if (cinfo^.err^.trace_level >= 2) then
- begin
- i := 0;
- while i < Pred(DCTSIZE2) do
- begin
- {$IFDEF DEBUG}
- TRACEMS8(j_common_ptr(cinfo), 2, JTRC_QUANTVALS,
- quant_ptr^.quantval[i], quant_ptr^.quantval[i+1],
- quant_ptr^.quantval[i+2], quant_ptr^.quantval[i+3],
- quant_ptr^.quantval[i+4], quant_ptr^.quantval[i+5],
- quant_ptr^.quantval[i+6], quant_ptr^.quantval[i+7]);
- {$ENDIF}
- Inc(i, 8);
- end;
- end;
- Dec( length, DCTSIZE2+1 );
- if (prec <> 0) then
- Dec( length, DCTSIZE2 );
- end;
- if (length <> 0) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH);
- { 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;
- get_dqt := TRUE;
- end; { get_dqt }
- {LOCAL}
- function get_dri (cinfo : j_decompress_ptr) : boolean;
- { Process a DRI marker }
- var
- length : INT32;
- tmp : uint;
- 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 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_dri := 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_dri := 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 );
- if (length <> 4) then
- ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH);
- { Read two bytes interpreted as an unsigned 16-bit integer.
- tmp 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_dri := 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 );
- tmp := (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_dri := 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( tmp, GETJOCTET( next_input_byte^));
- Inc( next_input_byte );
- {$IFDEF DEBUG}
- TRACEMS1(j_common_ptr(cinfo), 1, JTRC_DRI, tmp);
- {$ENDIF}
- cinfo^.restart_interval := tmp;
- { 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;
- get_dri := TRUE;
- end; { get_dri }
- { Routines for processing APPn and COM markers.
- These are either saved in memory or discarded, per application request.
- APP0 and APP14 are specially checked to see if they are
- JFIF and Adobe markers, respectively. }
- const
- APP0_DATA_LEN = 14; { Length of interesting data in APP0 }
- APP14_DATA_LEN = 12; { Length of interesting data in APP14 }
- APPN_DATA_LEN = 14; { Must be the largest of the above!! }
- {LOCAL}
- procedure examine_app0 (cinfo : j_decompress_ptr;
- var data : array of JOCTET;
- datalen : uint;
- remaining : INT32);
- { Examine first few bytes from an APP0.
- Take appropriate action if it is a JFIF marker.
- datalen is # of bytes at data[], remaining is length of rest of marker data.
- }
- {$IFDEF DEBUG}
- var
- totallen : INT32;
- {$ENDIF}
- begin
- {$IFDEF DEBUG}
- totallen := INT32(datalen) + remaining;
- {$ENDIF}
- if (datalen >= APP0_DATA_LEN) and
- (GETJOCTET(data[0]) = $4A) and
- (GETJOCTET(data[1]) = $46) and
- (GETJOCTET(data[2]) = $49) and
- (GETJOCTET(data[3]) = $46) and
- (GETJOCTET(data[4]) = 0) then
- begin
- { Found JFIF APP0 marker: save info }
- cinfo^.saw_JFIF_marker := TRUE;
- cinfo^.JFIF_major_version := GETJOCTET(data[5]);
- cinfo^.JFIF_minor_version := GETJOCTET(data[6]);
- cinfo^.density_unit := GETJOCTET(data[7]);
- cinfo^.X_density := (GETJOCTET(data[8]) shl 8) + GETJOCTET(data[9]);
- cinfo^.Y_density := (GETJOCTET(data[10]) shl 8) + GETJOCTET(data[11]);
- { Check version.
- Major version must be 1, anything else signals an incompatible change.
- (We used to treat this as an error, but now it's a nonfatal warning,
- because some bozo at Hijaak couldn't read the spec.)
- Minor version should be 0..2, but process anyway if newer. }
- if (cinfo^.JFIF_major_version <> 1) then
- WARNMS2(j_common_ptr(cinfo), JWRN_JFIF_MAJOR,
- cinfo^.JFIF_major_version, cinfo^.JFIF_minor_version);
- { Generate trace messages }
- {$IFDEF DEBUG}
- TRACEMS5(j_common_ptr(cinfo), 1, JTRC_JFIF,
- cinfo^.JFIF_major_version, cinfo^.JFIF_minor_version,
- cinfo^.X_density, cinfo^.Y_density, cinfo^.density_unit);
- { Validate thumbnail dimensions and issue appropriate messages }
- if (GETJOCTET(data[12]) or GETJOCTET(data[13])) <> 0 then
- TRACEMS2(j_common_ptr(cinfo), 1, JTRC_JFIF_THUMBNAIL,
- GETJOCTET(data[12]), GETJOCTET(data[13]));
- Dec(totallen, APP0_DATA_LEN);
- if (totallen <>
- ( INT32(GETJOCTET(data[12])) * INT32(GETJOCTET(data[13])) * INT32(3) )) then
- TRACEMS1(j_common_ptr(cinfo), 1, JTRC_JFIF_BADTHUMBNAILSIZE, int(totallen));
- {$ENDIF}
- end
- else
- if (datalen >= 6) and
- (GETJOCTET(data[0]) = $4A) and
- (GETJOCTET(data[1]) = $46) and
- (GETJOCTET(data[2]) = $58) and
- (GETJOCTET(data[3]) = $58) and
- (GETJOCTET(data[4]) = 0) then
- begin
- { Found JFIF "JFXX" extension APP0 marker }
- { The library doesn't actually do anything with these,
- but we try to produce a helpful trace message. }
- {$IFDEF DEBUG}
- case (GETJOCTET(data[5])) of
- $10:
- TRACEMS1(j_common_ptr(cinfo), 1, JTRC_THUMB_JPEG, int(totallen));
- $11:
- TRACEMS1(j_common_ptr(cinfo), 1, JTRC_THUMB_PALETTE, int(totallen));
- $13:
- TRACEMS1(j_common_ptr(cinfo), 1, JTRC_THUMB_RGB, int(totallen));
- else
- TRACEMS2(j_common_ptr(cinfo), 1, JTRC_JFIF_EXTENSION,
- GETJOCTET(data[5]), int(totallen));
- end;
- {$ENDIF}
- end
- else
- begin
- { Start of APP0 does not match "JFIF" or "JFXX", or too short }
- {$IFDEF DEBUG}
- TRACEMS1(j_common_ptr(cinfo), 1, JTRC_APP0, int(totallen));
- {$ENDIF}
- end;
- end;
- {LOCAL}
- procedure examine_app14 (cinfo : j_decompress_ptr;
- var data : array of JOCTET;
- datalen : uint;
- remaining : INT32);
- { Examine first few bytes from an APP14.
- Take appropriate action if it is an Adobe marker.
- datalen is # of bytes at data[], remaining is length of rest of marker data.
- }
- var
- {$IFDEF DEBUG}
- version, flags0, flags1,
- {$ENDIF}
- transform : uint;
- begin
- if (datalen >= APP14_DATA_LEN) and
- (GETJOCTET(data[0]) = $41) and
- (GETJOCTET(data[1]) = $64) and
- (GETJOCTET(data[2]) = $6F) and
- (GETJOCTET(data[3]) = $62) and
- (GETJOCTET(data[4]) = $65) then
- begin
- { Found Adobe APP14 marker }
- {$IFDEF DEBUG}
- version := (GETJOCTET(data[5]) shl 8) + GETJOCTET(data[6]);
- flags0 := (GETJOCTET(data[7]) shl 8) + GETJOCTET(data[8]);
- flags1 := (GETJOCTET(data[9]) shl 8) + GETJOCTET(data[10]);
- {$ENDIF}
- transform := GETJOCTET(data[11]);
- {$IFDEF DEBUG}
- TRACEMS4(j_common_ptr(cinfo), 1, JTRC_ADOBE, version, flags0, flags1, transform);
- {$ENDIF}
- cinfo^.saw_Adobe_marker := TRUE;
- cinfo^.Adobe_transform := UINT8 (transform);
- end
- else
- begin
- { Start of APP14 does not match "Adobe", or too short }
- {$IFDEF DEBUG}
- TRACEMS1(j_common_ptr(cinfo), 1, JTRC_APP14, int (datalen + remaining));
- {$ENDIF}
- end;
- end;
- {METHODDEF}
- function get_interesting_appn (cinfo : j_decompress_ptr) : boolean; far;
- { Process an APP0 or APP14 marker without saving it }
- var
- length : INT32;
- b : array[0..APPN_DATA_LEN-1] of JOCTET;
- i, numtoread : uint;
- 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 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_interesting_appn := 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_interesting_appn := 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);
- { get the interesting part of the marker data }
- if (length >= APPN_DATA_LEN) then
- numtoread := APPN_DATA_LEN
- else
- if (length > 0) then
- numtoread := uint(length)
- else
- numtoread := 0;
- for i := 0 to numtoread-1 do
- begin
- { Read a byte into b[i]. 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_interesting_appn := 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 );
- 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 --- 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
- {$IFDEF DEBUG}
- TRACEMS(j_common_ptr(cinfo), 1, JTRC_EOI);
- {$ENDIF}
- 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 my_marker_ptr(cinfo^.marker)^.
- process_APPn[cinfo^.unread_marker - int(M_APP0)](cinfo) then
- begin
- read_markers := JPEG_SUSPENDED;
- exit;
- end;
- M_COM:
- if not my_marker_ptr(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:
- {$IFDEF DEBUG}
- TRACEMS1(j_common_ptr(cinfo), 1, JTRC_PARMLESS_MARKER,
- cinfo^.unread_marker)
- {$ENDIF}
- ;
- 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 }
- {$IFDEF DEBUG}
- TRACEMS1(j_common_ptr(cinfo), 3, JTRC_RST,
- cinfo^.marker^.next_restart_num);
- {$ENDIF}
- 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.
- 2. Read forward until we find another marker, discarding intervening
- data. (In theory we could look ahead within the current bufferload,
- without having to discard data if we don't find the desired marker.
- This idea is not implemented here, in part because it makes behavior
- dependent on buffer size and chance buffer-boundary positions.)
- 3. Leave the marker unread (by failing to zero cinfo^.unread_marker).
- This will cause the entropy decoder to process an empty data segment,
- inserting dummy zeroes, and then we will reprocess the marker.
- #2 is appropriate if we think the desired marker lies ahead, while #3 is
- appropriate if the found marker is a future restart marker (indicating
- that we have missed the desired restart marker, probably because it got
- corrupted).
- We apply #2 or #3 if the found marker is a restart marker no more than
- two counts behind or ahead of the expected one. We also apply #2 if the
- found marker is not a legal JPEG marker code (it's certainly bogus data).
- If the found marker is a restart marker more than 2 counts away, we do #1
- (too much risk that the marker is erroneous; with luck we will be able to
- resync at some future point).
- For any valid non-restart JPEG marker, we apply #3. This keeps us from
- overrunning the end of a scan. An implementation limited to single-scan
- files might find it better to apply #2 for markers other than EOI, since
- any other marker would have to be bogus data in that case. }
- {GLOBAL}
- function jpeg_resync_to_restart(cinfo : j_decompress_ptr;
- desired : int) : boolean;
- var
- marker : int;
- action : int;
- begin
- marker := cinfo^.unread_marker;
- action := 1; { never used }
- { Always put up a warning. }
- WARNMS2(j_common_ptr(cinfo), JWRN_MUST_RESYNC, marker, desired);
- { Outer loop handles repeated decision after scanning forward. }
- repeat
- if (marker < int(M_SOF0)) then
- action := 2 { invalid marker }
- else
- if (marker < int(M_RST0)) or (marker > int(M_RST7)) then
- action := 3 { valid non-restart marker }
- else
- begin
- if (marker = (int(M_RST0) + ((desired+1) and 7))) or
- (marker = (int(M_RST0) + ((desired+2) and 7))) then
- action := 3 { one of the next two expected restarts }
- else
- if (marker = (int(M_RST0) + ((desired-1) and 7))) or
- (marker = (int(M_RST0) + ((desired-2) and 7))) then
- action := 2 { a prior restart, so advance }
- else
- action := 1; { desired restart or too far away }
- end;
- {$IFDEF DEBUG}
- TRACEMS2(j_common_ptr(cinfo), 4, JTRC_RECOVERY_ACTION, marker, action);
- {$ENDIF}
- case action of
- 1:
- { Discard marker and let entropy decoder resume processing. }
- begin
- cinfo^.unread_marker := 0;
- jpeg_resync_to_restart := TRUE;
- exit;
- end;
- 2:
- { Scan to the next marker, and repeat the decision loop. }
- begin
- if not next_marker(cinfo) then
- begin
- jpeg_resync_to_restart := FALSE;
- exit;
- end;
- marker := cinfo^.unread_marker;
- end;
- 3:
- { Return without advancing past this marker. }
- { Entropy decoder will be forced to process an empty segment. }
- begin
- jpeg_resync_to_restart := TRUE;
- exit;
- end;
- end; { case }
- Until false; { end loop }
- end; { jpeg_resync_to_restart }
- { Reset marker processing state to begin a fresh datastream. }
- {METHODDEF}
- procedure reset_marker_reader (cinfo : j_decompress_ptr); far;
- var
- marker : my_marker_ptr;
- begin
- marker := my_marker_ptr (cinfo^.marker);
- with cinfo^ do
- begin
- comp_info := NIL; { until allocated by get_sof }
- input_scan_number := 0; { no SOS seen yet }
- unread_marker := 0; { no pending marker }
- end;
- marker^.pub.saw_SOI := FALSE; { set internal state too }
- marker^.pub.saw_SOF := FALSE;
- marker^.pub.discarded_bytes := 0;
- marker^.cur_marker := NIL;
- end; { reset_marker_reader }
- { Initialize the marker reader module.
- This is called only once, when the decompression object is created. }
- {GLOBAL}
- procedure jinit_marker_reader (cinfo : j_decompress_ptr);
- var
- marker : my_marker_ptr;
- i : int;
- begin
- { Create subobject in permanent pool }
- marker := my_marker_ptr(
- cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_PERMANENT,
- SIZEOF(my_marker_reader))
- );
- cinfo^.marker := jpeg_marker_reader_ptr(marker);
- { Initialize method pointers }
- marker^.pub.reset_marker_reader := reset_marker_reader;
- marker^.pub.read_markers := read_markers;
- marker^.pub.read_restart_marker := read_restart_marker;
- { Initialize COM/APPn processing.
- By default, we examine and then discard APP0 and APP14,
- but simply discard COM and all other APPn. }
- marker^.process_COM := skip_variable;
- marker^.length_limit_COM := 0;
- for i := 0 to 16-1 do
- begin
- marker^.process_APPn[i] := skip_variable;
- marker^.length_limit_APPn[i] := 0;
- end;
- marker^.process_APPn[0] := get_interesting_appn;
- marker^.process_APPn[14] := get_interesting_appn;
- { Reset marker processing state }
- reset_marker_reader(cinfo);
- end; { jinit_marker_reader }
- { Control saving of COM and APPn markers into marker_list. }
- {$ifdef SAVE_MARKERS_SUPPORTED}
- {GLOBAL}
- procedure jpeg_save_markers (cinfo : j_decompress_ptr;
- marker_code : int;
- length_limit : uint);
- var
- marker : my_marker_ptr;
- maxlength : long;
- processor : jpeg_marker_parser_method;
- begin
- marker := my_marker_ptr (cinfo^.marker);
- { Length limit mustn't be larger than what we can allocate
- (should only be a concern in a 16-bit environment). }
- maxlength := cinfo^.mem^.max_alloc_chunk - SIZEOF(jpeg_marker_struct);
- if (long(length_limit) > maxlength) then
- length_limit := uint(maxlength);
- { Choose processor routine to use.
- APP0/APP14 have special requirements. }
- if (length_limit <> 0) then
- begin
- processor := save_marker;
- { If saving APP0/APP14, save at least enough for our internal use. }
- if (marker_code = int(M_APP0)) and (length_limit < APP0_DATA_LEN) then
- length_limit := APP0_DATA_LEN
- else
- if (marker_code = int(M_APP14)) and (length_limit < APP14_DATA_LEN) then
- length_limit := APP14_DATA_LEN;
- end
- else
- begin
- processor := skip_variable;
- { If discarding APP0/APP14, use our regular on-the-fly processor. }
- if (marker_code = int(M_APP0)) or (marker_code = int(M_APP14)) then
- processor := get_interesting_appn;
- end;
- if (marker_code = int(M_COM)) then
- begin
- marker^.process_COM := processor;
- marker^.length_limit_COM := length_limit;
- end
- else
- if (marker_code >= int(M_APP0)) and (marker_code <= int(M_APP15)) then
- begin
- marker^.process_APPn[marker_code - int(M_APP0)] := processor;
- marker^.length_limit_APPn[marker_code - int(M_APP0)] := length_limit;
- end
- else
- ERREXIT1(j_common_ptr(cinfo), JERR_UNKNOWN_MARKER, marker_code);
- end;
- {$endif} { SAVE_MARKERS_SUPPORTED }
- { Install a special processing method for COM or APPn markers. }
- {GLOBAL}
- procedure jpeg_set_marker_processor (cinfo : j_decompress_ptr;
- marker_code : int;
- routine : jpeg_marker_parser_method);
- var
- marker : my_marker_ptr;
- begin
- marker := my_marker_ptr (cinfo^.marker);
- if (marker_code = int(M_COM)) then
- marker^.process_COM := routine
- else
- if (marker_code >= int(M_APP0)) and (marker_code <= int(M_APP15)) then
- marker^.process_APPn[marker_code - int(M_APP0)] := routine
- else
- ERREXIT1(j_common_ptr(cinfo), JERR_UNKNOWN_MARKER, marker_code);
- end;
- end.
|