12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648 |
- 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;
-
- if numtoread > 0 then
- begin
- 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;
- 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.
|