| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810 |
- /* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0
- specification is now totally obsolete and deprecated for new applications and
- images. This file was was created solely in order to read unconverted images
- still present on some users' computer systems. It will never be extended
- to write such files. Writing new-style JPEG compressed TIFFs is implemented
- in tif_jpeg.c.
- The code is carefully crafted to robustly read all gathered JPEG-in-TIFF
- testfiles, and anticipate as much as possible all other... But still, it may
- fail on some. If you encounter problems, please report them on the TIFF
- mailing list and/or to Joris Van Damme <info@awaresystems.be>.
- Please read the file called "TIFF Technical Note #2" if you need to be
- convinced this compression scheme is bad and breaks TIFF. That document
- is linked to from the LibTiff site <http://www.remotesensing.org/libtiff/>
- and from AWare Systems' TIFF section
- <http://www.awaresystems.be/imaging/tiff.html>. It is also absorbed
- in Adobe's specification supplements, marked "draft" up to this day, but
- supported by the TIFF community.
- This file interfaces with Release 6B of the JPEG Library written by the
- Independent JPEG Group. Previous versions of this file required a hack inside
- the LibJpeg library. This version no longer requires that. Remember to
- remove the hack if you update from the old version.
- Copyright (c) Joris Van Damme <info@awaresystems.be>
- Copyright (c) AWare Systems <http://www.awaresystems.be/>
- The licence agreement for this file is the same as the rest of the LibTiff
- library.
- IN NO EVENT SHALL JORIS VAN DAMME OR AWARE SYSTEMS BE LIABLE FOR
- ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
- OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
- LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- OF THIS SOFTWARE.
- Joris Van Damme and/or AWare Systems may be available for custom
- development. If you like what you see, and need anything similar or related,
- contact <info@awaresystems.be>.
- */
- /* What is what, and what is not?
- This decoder starts with an input stream, that is essentially the
- JpegInterchangeFormat stream, if any, followed by the strile data, if any.
- This stream is read in OJPEGReadByte and related functions.
- It analyzes the start of this stream, until it encounters non-marker data,
- i.e. compressed image data. Some of the header markers it sees have no actual
- content, like the SOI marker, and APP/COM markers that really shouldn't even
- be there. Some other markers do have content, and the valuable bits and
- pieces of information in these markers are saved, checking all to verify that
- the stream is more or less within expected bounds. This happens inside the
- OJPEGReadHeaderInfoSecStreamXxx functions.
- Some OJPEG imagery contains no valid JPEG header markers. This situation is
- picked up on if we've seen no SOF marker when we're at the start of the
- compressed image data. In this case, the tables are read from JpegXxxTables
- tags, and the other bits and pieces of information is initialized to its most
- basic value. This is implemented in the OJPEGReadHeaderInfoSecTablesXxx
- functions.
- When this is complete, a good and valid JPEG header can be assembled, and
- this is passed through to LibJpeg. When that's done, the remainder of the
- input stream, i.e. the compressed image data, can be passed through
- unchanged. This is done in OJPEGWriteStream functions.
- LibTiff rightly expects to know the subsampling values before decompression.
- Just like in new-style JPEG-in-TIFF, though, or even more so, actually, the
- YCbCrsubsampling tag is notoriously unreliable. To correct these tag values
- with the ones inside the JPEG stream, the first part of the input stream is
- pre-scanned in OJPEGSubsamplingCorrect, making no note of any other data,
- reporting no warnings or errors, up to the point where either these values
- are read, or it's clear they aren't there. This means that some of the data
- is read twice, but we feel speed in correcting these values is important
- enough to warrant this sacrifice. Although there is currently no define or
- other configuration mechanism to disable this behavior, the actual header
- scanning is build to robustly respond with error report if it should
- encounter an uncorrected mismatch of subsampling values. See
- OJPEGReadHeaderInfoSecStreamSof.
- The restart interval and restart markers are the most tricky part... The
- restart interval can be specified in a tag. It can also be set inside the
- input JPEG stream. It can be used inside the input JPEG stream. If reading
- from strile data, we've consistently discovered the need to insert restart
- markers in between the different striles, as is also probably the most likely
- interpretation of the original TIFF 6.0 specification. With all this setting
- of interval, and actual use of markers that is not predictable at the time of
- valid JPEG header assembly, the restart thing may turn out the Achilles heel
- of this implementation. Fortunately, most OJPEG writer vendors succeed in
- reading back what they write, which may be the reason why we've been able to
- discover ways that seem to work.
- Some special provision is made for planarconfig separate OJPEG files. These
- seem to consistently contain header info, a SOS marker, a plane, SOS marker,
- plane, SOS, and plane. This may or may not be a valid JPEG configuration, we
- don't know and don't care. We want LibTiff to be able to access the planes
- individually, without huge buffering inside LibJpeg, anyway. So we compose
- headers to feed to LibJpeg, in this case, that allow us to pass a single
- plane such that LibJpeg sees a valid single-channel JPEG stream. Locating
- subsequent SOS markers, and thus subsequent planes, is done inside
- OJPEGReadSecondarySos.
- The benefit of the scheme is... that it works, basically. We know of no other
- that does. It works without checking software tag, or otherwise going about
- things in an OJPEG flavor specific manner. Instead, it is a single scheme,
- that covers the cases with and without JpegInterchangeFormat, with and
- without striles, with part of the header in JpegInterchangeFormat and
- remainder in first strile, etc. It is forgiving and robust, may likely work
- with OJPEG flavors we've not seen yet, and makes most out of the data.
- Another nice side-effect is that a complete JPEG single valid stream is build
- if planarconfig is not separate (vast majority). We may one day use that to
- build converters to JPEG, and/or to new-style JPEG compression inside TIFF.
- A disadvantage is the lack of random access to the individual striles. This
- is the reason for much of the complicated restart-and-position stuff inside
- OJPEGPreDecode. Applications would do well accessing all striles in order, as
- this will result in a single sequential scan of the input stream, and no
- restarting of LibJpeg decoding session.
- */
- #define WIN32_LEAN_AND_MEAN
- #define VC_EXTRALEAN
- #include "tiffiop.h"
- #ifdef OJPEG_SUPPORT
- /* Configuration defines here are:
- * JPEG_ENCAP_EXTERNAL: The normal way to call libjpeg, uses longjump. In some
- * environments, like eg LibTiffDelphi, this is not possible. For this reason,
- * the actual calls to libjpeg, with longjump stuff, are encapsulated in
- * dedicated functions. When JPEG_ENCAP_EXTERNAL is defined, these encapsulating
- * functions are declared external to this unit, and can be defined elsewhere to
- * use stuff other then longjump. The default mode, without JPEG_ENCAP_EXTERNAL,
- * implements the call encapsulators here, internally, with normal longjump.
- * SETJMP, LONGJMP, JMP_BUF: On some machines/environments a longjump equivalent
- * is conveniently available, but still it may be worthwhile to use _setjmp or
- * sigsetjmp in place of plain setjmp. These macros will make it easier. It is
- * useless to fiddle with these if you define JPEG_ENCAP_EXTERNAL. OJPEG_BUFFER:
- * Define the size of the desired buffer here. Should be small enough so as to
- * guarantee instant processing, optimal streaming and optimal use of processor
- * cache, but also big enough so as to not result in significant call overhead.
- * It should be at least a few bytes to accommodate some structures (this is
- * verified in asserts), but it would not be sensible to make it this small
- * anyway, and it should be at most 64K since it is indexed with uint16_t. We
- * recommend 2K. EGYPTIANWALK: You could also define EGYPTIANWALK here, but it
- * is not used anywhere and has absolutely no effect. That is why most people
- * insist the EGYPTIANWALK is a bit silly.
- */
- /* define LIBJPEG_ENCAP_EXTERNAL */
- #define SETJMP(jbuf) setjmp(jbuf)
- #define LONGJMP(jbuf, code) longjmp(jbuf, code)
- #define JMP_BUF jmp_buf
- #define OJPEG_BUFFER 2048
- /* define EGYPTIANWALK */
- #define JPEG_MARKER_SOF0 0xC0
- #define JPEG_MARKER_SOF1 0xC1
- #define JPEG_MARKER_SOF3 0xC3
- #define JPEG_MARKER_DHT 0xC4
- #define JPEG_MARKER_RST0 0XD0
- #define JPEG_MARKER_SOI 0xD8
- #define JPEG_MARKER_EOI 0xD9
- #define JPEG_MARKER_SOS 0xDA
- #define JPEG_MARKER_DQT 0xDB
- #define JPEG_MARKER_DRI 0xDD
- #define JPEG_MARKER_APP0 0xE0
- #define JPEG_MARKER_COM 0xFE
- #define FIELD_OJPEG_JPEGINTERCHANGEFORMAT (FIELD_CODEC + 0)
- #define FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH (FIELD_CODEC + 1)
- #define FIELD_OJPEG_JPEGQTABLES (FIELD_CODEC + 2)
- #define FIELD_OJPEG_JPEGDCTABLES (FIELD_CODEC + 3)
- #define FIELD_OJPEG_JPEGACTABLES (FIELD_CODEC + 4)
- #define FIELD_OJPEG_JPEGPROC (FIELD_CODEC + 5)
- #define FIELD_OJPEG_JPEGRESTARTINTERVAL (FIELD_CODEC + 6)
- static const TIFFField ojpegFields[] = {
- {TIFFTAG_JPEGIFOFFSET, 1, 1, TIFF_LONG8, 0, TIFF_SETGET_UINT64,
- FIELD_OJPEG_JPEGINTERCHANGEFORMAT, TRUE, FALSE, "JpegInterchangeFormat",
- NULL},
- {TIFFTAG_JPEGIFBYTECOUNT, 1, 1, TIFF_LONG8, 0, TIFF_SETGET_UINT64,
- FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH, TRUE, FALSE,
- "JpegInterchangeFormatLength", NULL},
- {TIFFTAG_JPEGQTABLES, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_LONG8, 0,
- TIFF_SETGET_C32_UINT64, FIELD_OJPEG_JPEGQTABLES, FALSE, TRUE,
- "JpegQTables", NULL},
- {TIFFTAG_JPEGDCTABLES, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_LONG8, 0,
- TIFF_SETGET_C32_UINT64, FIELD_OJPEG_JPEGDCTABLES, FALSE, TRUE,
- "JpegDcTables", NULL},
- {TIFFTAG_JPEGACTABLES, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_LONG8, 0,
- TIFF_SETGET_C32_UINT64, FIELD_OJPEG_JPEGACTABLES, FALSE, TRUE,
- "JpegAcTables", NULL},
- {TIFFTAG_JPEGPROC, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- FIELD_OJPEG_JPEGPROC, FALSE, FALSE, "JpegProc", NULL},
- {TIFFTAG_JPEGRESTARTINTERVAL, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- FIELD_OJPEG_JPEGRESTARTINTERVAL, FALSE, FALSE, "JpegRestartInterval",
- NULL},
- };
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- #include <setjmp.h>
- #endif
- #include "jerror.h"
- #include "jpeglib.h"
- #ifndef TIFF_jpeg_source_mgr_defined
- #define TIFF_jpeg_source_mgr_defined
- typedef struct jpeg_source_mgr jpeg_source_mgr;
- #endif
- #ifndef TIFF_jpeg_error_mgr_defined
- #define TIFF_jpeg_error_mgr_defined
- typedef struct jpeg_error_mgr jpeg_error_mgr;
- #endif
- typedef struct jpeg_common_struct jpeg_common_struct;
- typedef struct jpeg_decompress_struct jpeg_decompress_struct;
- typedef enum
- {
- osibsNotSetYet,
- osibsJpegInterchangeFormat,
- osibsStrile,
- osibsEof
- } OJPEGStateInBufferSource;
- typedef enum
- {
- ososSoi,
- ososQTable0,
- ososQTable1,
- ososQTable2,
- ososQTable3,
- ososDcTable0,
- ososDcTable1,
- ososDcTable2,
- ososDcTable3,
- ososAcTable0,
- ososAcTable1,
- ososAcTable2,
- ososAcTable3,
- ososDri,
- ososSof,
- ososSos,
- ososCompressed,
- ososRst,
- ososEoi
- } OJPEGStateOutState;
- typedef struct
- {
- TIFF *tif;
- int decoder_ok;
- int error_in_raw_data_decoding;
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- JMP_BUF exit_jmpbuf;
- #endif
- TIFFVGetMethod vgetparent;
- TIFFVSetMethod vsetparent;
- TIFFPrintMethod printdir;
- uint64_t file_size;
- uint32_t image_width;
- uint32_t image_length;
- uint32_t strile_width;
- uint32_t strile_length;
- uint32_t strile_length_total;
- uint8_t samples_per_pixel;
- uint8_t plane_sample_offset;
- uint8_t samples_per_pixel_per_plane;
- uint64_t jpeg_interchange_format;
- uint64_t jpeg_interchange_format_length;
- uint8_t jpeg_proc;
- uint8_t subsamplingcorrect;
- uint8_t subsamplingcorrect_done;
- uint8_t subsampling_tag;
- uint8_t subsampling_hor;
- uint8_t subsampling_ver;
- uint8_t subsampling_force_desubsampling_inside_decompression;
- uint8_t qtable_offset_count;
- uint8_t dctable_offset_count;
- uint8_t actable_offset_count;
- uint64_t qtable_offset[3];
- uint64_t dctable_offset[3];
- uint64_t actable_offset[3];
- uint8_t *qtable[4];
- uint8_t *dctable[4];
- uint8_t *actable[4];
- uint16_t restart_interval;
- uint8_t restart_index;
- uint8_t sof_log;
- uint8_t sof_marker_id;
- uint32_t sof_x;
- uint32_t sof_y;
- uint8_t sof_c[3];
- uint8_t sof_hv[3];
- uint8_t sof_tq[3];
- uint8_t sos_cs[3];
- uint8_t sos_tda[3];
- struct
- {
- uint8_t log;
- OJPEGStateInBufferSource in_buffer_source;
- uint32_t in_buffer_next_strile;
- uint64_t in_buffer_file_pos;
- uint64_t in_buffer_file_togo;
- } sos_end[3];
- uint8_t readheader_done;
- uint8_t writeheader_done;
- uint16_t write_cursample;
- uint32_t write_curstrile;
- uint8_t libjpeg_session_active;
- uint8_t libjpeg_jpeg_query_style;
- jpeg_error_mgr libjpeg_jpeg_error_mgr;
- jpeg_decompress_struct libjpeg_jpeg_decompress_struct;
- jpeg_source_mgr libjpeg_jpeg_source_mgr;
- uint8_t subsampling_convert_log;
- uint32_t subsampling_convert_ylinelen;
- uint32_t subsampling_convert_ylines;
- uint32_t subsampling_convert_clinelen;
- uint32_t subsampling_convert_clines;
- uint32_t subsampling_convert_ybuflen;
- uint32_t subsampling_convert_cbuflen;
- uint32_t subsampling_convert_ycbcrbuflen;
- uint8_t *subsampling_convert_ycbcrbuf;
- uint8_t *subsampling_convert_ybuf;
- uint8_t *subsampling_convert_cbbuf;
- uint8_t *subsampling_convert_crbuf;
- uint32_t subsampling_convert_ycbcrimagelen;
- uint8_t **subsampling_convert_ycbcrimage;
- uint32_t subsampling_convert_clinelenout;
- uint32_t subsampling_convert_state;
- uint32_t bytes_per_line; /* if the codec outputs subsampled data, a 'line'
- in bytes_per_line */
- uint32_t lines_per_strile; /* and lines_per_strile means subsampling_ver
- desubsampled rows */
- OJPEGStateInBufferSource in_buffer_source;
- uint32_t in_buffer_next_strile;
- uint32_t in_buffer_strile_count;
- uint64_t in_buffer_file_pos;
- uint8_t in_buffer_file_pos_log;
- uint64_t in_buffer_file_togo;
- uint16_t in_buffer_togo;
- uint8_t *in_buffer_cur;
- uint8_t in_buffer[OJPEG_BUFFER];
- OJPEGStateOutState out_state;
- uint8_t out_buffer[OJPEG_BUFFER];
- uint8_t *skip_buffer;
- } OJPEGState;
- static int OJPEGVGetField(TIFF *tif, uint32_t tag, va_list ap);
- static int OJPEGVSetField(TIFF *tif, uint32_t tag, va_list ap);
- static void OJPEGPrintDir(TIFF *tif, FILE *fd, long flags);
- static int OJPEGFixupTags(TIFF *tif);
- static int OJPEGSetupDecode(TIFF *tif);
- static int OJPEGPreDecode(TIFF *tif, uint16_t s);
- static int OJPEGPreDecodeSkipRaw(TIFF *tif);
- static int OJPEGPreDecodeSkipScanlines(TIFF *tif);
- static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s);
- static int OJPEGDecodeRaw(TIFF *tif, uint8_t *buf, tmsize_t cc);
- static int OJPEGDecodeScanlines(TIFF *tif, uint8_t *buf, tmsize_t cc);
- static void OJPEGPostDecode(TIFF *tif, uint8_t *buf, tmsize_t cc);
- static int OJPEGSetupEncode(TIFF *tif);
- static int OJPEGPreEncode(TIFF *tif, uint16_t s);
- static int OJPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s);
- static int OJPEGPostEncode(TIFF *tif);
- static void OJPEGCleanup(TIFF *tif);
- static void OJPEGSubsamplingCorrect(TIFF *tif);
- static int OJPEGReadHeaderInfo(TIFF *tif);
- static int OJPEGReadSecondarySos(TIFF *tif, uint16_t s);
- static int OJPEGWriteHeaderInfo(TIFF *tif);
- static void OJPEGLibjpegSessionAbort(TIFF *tif);
- static int OJPEGReadHeaderInfoSec(TIFF *tif);
- static int OJPEGReadHeaderInfoSecStreamDri(TIFF *tif);
- static int OJPEGReadHeaderInfoSecStreamDqt(TIFF *tif);
- static int OJPEGReadHeaderInfoSecStreamDht(TIFF *tif);
- static int OJPEGReadHeaderInfoSecStreamSof(TIFF *tif, uint8_t marker_id);
- static int OJPEGReadHeaderInfoSecStreamSos(TIFF *tif);
- static int OJPEGReadHeaderInfoSecTablesQTable(TIFF *tif);
- static int OJPEGReadHeaderInfoSecTablesDcTable(TIFF *tif);
- static int OJPEGReadHeaderInfoSecTablesAcTable(TIFF *tif);
- static int OJPEGReadBufferFill(OJPEGState *sp);
- static int OJPEGReadByte(OJPEGState *sp, uint8_t *byte);
- static int OJPEGReadBytePeek(OJPEGState *sp, uint8_t *byte);
- static void OJPEGReadByteAdvance(OJPEGState *sp);
- static int OJPEGReadWord(OJPEGState *sp, uint16_t *word);
- static int OJPEGReadBlock(OJPEGState *sp, uint16_t len, void *mem);
- static void OJPEGReadSkip(OJPEGState *sp, uint16_t len);
- static int OJPEGWriteStream(TIFF *tif, void **mem, uint32_t *len);
- static void OJPEGWriteStreamSoi(TIFF *tif, void **mem, uint32_t *len);
- static void OJPEGWriteStreamQTable(TIFF *tif, uint8_t table_index, void **mem,
- uint32_t *len);
- static void OJPEGWriteStreamDcTable(TIFF *tif, uint8_t table_index, void **mem,
- uint32_t *len);
- static void OJPEGWriteStreamAcTable(TIFF *tif, uint8_t table_index, void **mem,
- uint32_t *len);
- static void OJPEGWriteStreamDri(TIFF *tif, void **mem, uint32_t *len);
- static void OJPEGWriteStreamSof(TIFF *tif, void **mem, uint32_t *len);
- static void OJPEGWriteStreamSos(TIFF *tif, void **mem, uint32_t *len);
- static int OJPEGWriteStreamCompressed(TIFF *tif, void **mem, uint32_t *len);
- static void OJPEGWriteStreamRst(TIFF *tif, void **mem, uint32_t *len);
- static void OJPEGWriteStreamEoi(TIFF *tif, void **mem, uint32_t *len);
- #ifdef LIBJPEG_ENCAP_EXTERNAL
- extern int jpeg_create_decompress_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo);
- extern int jpeg_read_header_encap(OJPEGState *sp, jpeg_decompress_struct *cinfo,
- uint8_t require_image);
- extern int jpeg_start_decompress_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo);
- extern int jpeg_read_scanlines_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo,
- void *scanlines, uint32_t max_lines);
- extern int jpeg_read_raw_data_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo, void *data,
- uint32_t max_lines);
- extern void jpeg_encap_unwind(TIFF *tif);
- #else
- static int jpeg_create_decompress_encap(OJPEGState *sp,
- jpeg_decompress_struct *j);
- static int jpeg_read_header_encap(OJPEGState *sp, jpeg_decompress_struct *cinfo,
- uint8_t require_image);
- static int jpeg_start_decompress_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo);
- static int jpeg_read_scanlines_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo,
- void *scanlines, uint32_t max_lines);
- static int jpeg_read_raw_data_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo, void *data,
- uint32_t max_lines);
- static void jpeg_encap_unwind(TIFF *tif);
- #endif
- static void OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct *cinfo);
- static void OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct *cinfo);
- static void OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct *cinfo);
- static boolean
- OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct *cinfo);
- static void
- OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct *cinfo,
- long num_bytes);
- static boolean
- OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct *cinfo,
- int desired);
- static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct *cinfo);
- int TIFFInitOJPEG(TIFF *tif, int scheme)
- {
- static const char module[] = "TIFFInitOJPEG";
- OJPEGState *sp;
- (void)scheme;
- assert(scheme == COMPRESSION_OJPEG);
- /*
- * Merge codec-specific tag information.
- */
- if (!_TIFFMergeFields(tif, ojpegFields, TIFFArrayCount(ojpegFields)))
- {
- TIFFErrorExtR(tif, module,
- "Merging Old JPEG codec-specific tags failed");
- return 0;
- }
- /* state block */
- sp = _TIFFmallocExt(tif, sizeof(OJPEGState));
- if (sp == NULL)
- {
- TIFFErrorExtR(tif, module, "No space for OJPEG state block");
- return (0);
- }
- _TIFFmemset(sp, 0, sizeof(OJPEGState));
- sp->tif = tif;
- sp->jpeg_proc = 1;
- sp->subsampling_hor = 2;
- sp->subsampling_ver = 2;
- TIFFSetField(tif, TIFFTAG_YCBCRSUBSAMPLING, 2, 2);
- /* tif codec methods */
- tif->tif_fixuptags = OJPEGFixupTags;
- tif->tif_setupdecode = OJPEGSetupDecode;
- tif->tif_predecode = OJPEGPreDecode;
- tif->tif_postdecode = OJPEGPostDecode;
- tif->tif_decoderow = OJPEGDecode;
- tif->tif_decodestrip = OJPEGDecode;
- tif->tif_decodetile = OJPEGDecode;
- tif->tif_setupencode = OJPEGSetupEncode;
- tif->tif_preencode = OJPEGPreEncode;
- tif->tif_postencode = OJPEGPostEncode;
- tif->tif_encoderow = OJPEGEncode;
- tif->tif_encodestrip = OJPEGEncode;
- tif->tif_encodetile = OJPEGEncode;
- tif->tif_cleanup = OJPEGCleanup;
- tif->tif_data = (uint8_t *)sp;
- /* tif tag methods */
- sp->vgetparent = tif->tif_tagmethods.vgetfield;
- tif->tif_tagmethods.vgetfield = OJPEGVGetField;
- sp->vsetparent = tif->tif_tagmethods.vsetfield;
- tif->tif_tagmethods.vsetfield = OJPEGVSetField;
- sp->printdir = tif->tif_tagmethods.printdir;
- tif->tif_tagmethods.printdir = OJPEGPrintDir;
- /* Some OJPEG files don't have strip or tile offsets or bytecounts tags.
- Some others do, but have totally meaningless or corrupt values
- in these tags. In these cases, the JpegInterchangeFormat stream is
- reliable. In any case, this decoder reads the compressed data itself,
- from the most reliable locations, and we need to notify encapsulating
- LibTiff not to read raw strips or tiles for us. */
- tif->tif_flags |= TIFF_NOREADRAW;
- return (1);
- }
- static int OJPEGVGetField(TIFF *tif, uint32_t tag, va_list ap)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- switch (tag)
- {
- case TIFFTAG_JPEGIFOFFSET:
- *va_arg(ap, uint64_t *) = (uint64_t)sp->jpeg_interchange_format;
- break;
- case TIFFTAG_JPEGIFBYTECOUNT:
- *va_arg(ap, uint64_t *) =
- (uint64_t)sp->jpeg_interchange_format_length;
- break;
- case TIFFTAG_YCBCRSUBSAMPLING:
- if (sp->subsamplingcorrect_done == 0)
- OJPEGSubsamplingCorrect(tif);
- *va_arg(ap, uint16_t *) = (uint16_t)sp->subsampling_hor;
- *va_arg(ap, uint16_t *) = (uint16_t)sp->subsampling_ver;
- break;
- case TIFFTAG_JPEGQTABLES:
- *va_arg(ap, uint32_t *) = (uint32_t)sp->qtable_offset_count;
- *va_arg(ap, const void **) = (const void *)sp->qtable_offset;
- break;
- case TIFFTAG_JPEGDCTABLES:
- *va_arg(ap, uint32_t *) = (uint32_t)sp->dctable_offset_count;
- *va_arg(ap, const void **) = (const void *)sp->dctable_offset;
- break;
- case TIFFTAG_JPEGACTABLES:
- *va_arg(ap, uint32_t *) = (uint32_t)sp->actable_offset_count;
- *va_arg(ap, const void **) = (const void *)sp->actable_offset;
- break;
- case TIFFTAG_JPEGPROC:
- *va_arg(ap, uint16_t *) = (uint16_t)sp->jpeg_proc;
- break;
- case TIFFTAG_JPEGRESTARTINTERVAL:
- *va_arg(ap, uint16_t *) = sp->restart_interval;
- break;
- default:
- return (*sp->vgetparent)(tif, tag, ap);
- }
- return (1);
- }
- static int OJPEGVSetField(TIFF *tif, uint32_t tag, va_list ap)
- {
- static const char module[] = "OJPEGVSetField";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint32_t ma;
- uint64_t *mb;
- uint32_t n;
- const TIFFField *fip;
- switch (tag)
- {
- case TIFFTAG_JPEGIFOFFSET:
- sp->jpeg_interchange_format = (uint64_t)va_arg(ap, uint64_t);
- break;
- case TIFFTAG_JPEGIFBYTECOUNT:
- sp->jpeg_interchange_format_length = (uint64_t)va_arg(ap, uint64_t);
- break;
- case TIFFTAG_YCBCRSUBSAMPLING:
- sp->subsampling_tag = 1;
- sp->subsampling_hor = (uint8_t)va_arg(ap, uint16_vap);
- sp->subsampling_ver = (uint8_t)va_arg(ap, uint16_vap);
- tif->tif_dir.td_ycbcrsubsampling[0] = sp->subsampling_hor;
- tif->tif_dir.td_ycbcrsubsampling[1] = sp->subsampling_ver;
- break;
- case TIFFTAG_JPEGQTABLES:
- ma = (uint32_t)va_arg(ap, uint32_t);
- if (ma != 0)
- {
- if (ma > 3)
- {
- TIFFErrorExtR(tif, module,
- "JpegQTables tag has incorrect count");
- return (0);
- }
- sp->qtable_offset_count = (uint8_t)ma;
- mb = (uint64_t *)va_arg(ap, uint64_t *);
- for (n = 0; n < ma; n++)
- sp->qtable_offset[n] = mb[n];
- }
- break;
- case TIFFTAG_JPEGDCTABLES:
- ma = (uint32_t)va_arg(ap, uint32_t);
- if (ma != 0)
- {
- if (ma > 3)
- {
- TIFFErrorExtR(tif, module,
- "JpegDcTables tag has incorrect count");
- return (0);
- }
- sp->dctable_offset_count = (uint8_t)ma;
- mb = (uint64_t *)va_arg(ap, uint64_t *);
- for (n = 0; n < ma; n++)
- sp->dctable_offset[n] = mb[n];
- }
- break;
- case TIFFTAG_JPEGACTABLES:
- ma = (uint32_t)va_arg(ap, uint32_t);
- if (ma != 0)
- {
- if (ma > 3)
- {
- TIFFErrorExtR(tif, module,
- "JpegAcTables tag has incorrect count");
- return (0);
- }
- sp->actable_offset_count = (uint8_t)ma;
- mb = (uint64_t *)va_arg(ap, uint64_t *);
- for (n = 0; n < ma; n++)
- sp->actable_offset[n] = mb[n];
- }
- break;
- case TIFFTAG_JPEGPROC:
- sp->jpeg_proc = (uint8_t)va_arg(ap, uint16_vap);
- break;
- case TIFFTAG_JPEGRESTARTINTERVAL:
- sp->restart_interval = (uint16_t)va_arg(ap, uint16_vap);
- break;
- default:
- return (*sp->vsetparent)(tif, tag, ap);
- }
- fip = TIFFFieldWithTag(tif, tag);
- if (fip == NULL) /* shouldn't happen */
- return (0);
- TIFFSetFieldBit(tif, fip->field_bit);
- tif->tif_flags |= TIFF_DIRTYDIRECT;
- return (1);
- }
- static void OJPEGPrintDir(TIFF *tif, FILE *fd, long flags)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t m;
- (void)flags;
- assert(sp != NULL);
- if (TIFFFieldSet(tif, FIELD_OJPEG_JPEGINTERCHANGEFORMAT))
- fprintf(fd, " JpegInterchangeFormat: %" PRIu64 "\n",
- (uint64_t)sp->jpeg_interchange_format);
- if (TIFFFieldSet(tif, FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH))
- fprintf(fd, " JpegInterchangeFormatLength: %" PRIu64 "\n",
- (uint64_t)sp->jpeg_interchange_format_length);
- if (TIFFFieldSet(tif, FIELD_OJPEG_JPEGQTABLES))
- {
- fprintf(fd, " JpegQTables:");
- for (m = 0; m < sp->qtable_offset_count; m++)
- fprintf(fd, " %" PRIu64, (uint64_t)sp->qtable_offset[m]);
- fprintf(fd, "\n");
- }
- if (TIFFFieldSet(tif, FIELD_OJPEG_JPEGDCTABLES))
- {
- fprintf(fd, " JpegDcTables:");
- for (m = 0; m < sp->dctable_offset_count; m++)
- fprintf(fd, " %" PRIu64, (uint64_t)sp->dctable_offset[m]);
- fprintf(fd, "\n");
- }
- if (TIFFFieldSet(tif, FIELD_OJPEG_JPEGACTABLES))
- {
- fprintf(fd, " JpegAcTables:");
- for (m = 0; m < sp->actable_offset_count; m++)
- fprintf(fd, " %" PRIu64, (uint64_t)sp->actable_offset[m]);
- fprintf(fd, "\n");
- }
- if (TIFFFieldSet(tif, FIELD_OJPEG_JPEGPROC))
- fprintf(fd, " JpegProc: %" PRIu8 "\n", sp->jpeg_proc);
- if (TIFFFieldSet(tif, FIELD_OJPEG_JPEGRESTARTINTERVAL))
- fprintf(fd, " JpegRestartInterval: %" PRIu16 "\n",
- sp->restart_interval);
- if (sp->printdir)
- (*sp->printdir)(tif, fd, flags);
- }
- static int OJPEGFixupTags(TIFF *tif)
- {
- (void)tif;
- return (1);
- }
- static int OJPEGSetupDecode(TIFF *tif)
- {
- static const char module[] = "OJPEGSetupDecode";
- TIFFWarningExtR(tif, module,
- "Deprecated and troublesome old-style JPEG compression "
- "mode, please convert to new-style JPEG compression and "
- "notify vendor of writing software");
- return (1);
- }
- static int OJPEGPreDecode(TIFF *tif, uint16_t s)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint32_t m;
- if (sp->subsamplingcorrect_done == 0)
- OJPEGSubsamplingCorrect(tif);
- if (sp->readheader_done == 0)
- {
- if (OJPEGReadHeaderInfo(tif) == 0)
- return (0);
- }
- if (sp->sos_end[s].log == 0)
- {
- if (OJPEGReadSecondarySos(tif, s) == 0)
- return (0);
- }
- if (isTiled(tif))
- m = tif->tif_curtile;
- else
- m = tif->tif_curstrip;
- if ((sp->writeheader_done != 0) &&
- ((sp->write_cursample != s) || (sp->write_curstrile > m)))
- {
- if (sp->libjpeg_session_active != 0)
- OJPEGLibjpegSessionAbort(tif);
- sp->writeheader_done = 0;
- }
- if (sp->writeheader_done == 0)
- {
- sp->plane_sample_offset = (uint8_t)s;
- sp->write_cursample = s;
- sp->write_curstrile = s * tif->tif_dir.td_stripsperimage;
- if ((sp->in_buffer_file_pos_log == 0) ||
- (sp->in_buffer_file_pos - sp->in_buffer_togo !=
- sp->sos_end[s].in_buffer_file_pos))
- {
- sp->in_buffer_source = sp->sos_end[s].in_buffer_source;
- sp->in_buffer_next_strile = sp->sos_end[s].in_buffer_next_strile;
- sp->in_buffer_file_pos = sp->sos_end[s].in_buffer_file_pos;
- sp->in_buffer_file_pos_log = 0;
- sp->in_buffer_file_togo = sp->sos_end[s].in_buffer_file_togo;
- sp->in_buffer_togo = 0;
- sp->in_buffer_cur = 0;
- }
- if (OJPEGWriteHeaderInfo(tif) == 0)
- return (0);
- }
- sp->subsampling_convert_state = 0;
- while (sp->write_curstrile < m)
- {
- if (sp->libjpeg_jpeg_query_style == 0)
- {
- if (OJPEGPreDecodeSkipRaw(tif) == 0)
- return (0);
- }
- else
- {
- if (OJPEGPreDecodeSkipScanlines(tif) == 0)
- return (0);
- }
- sp->write_curstrile++;
- }
- sp->decoder_ok = 1;
- return (1);
- }
- static int OJPEGPreDecodeSkipRaw(TIFF *tif)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint32_t m;
- m = sp->lines_per_strile;
- if (sp->subsampling_convert_state != 0)
- {
- if (sp->subsampling_convert_clines - sp->subsampling_convert_state >= m)
- {
- sp->subsampling_convert_state += m;
- if (sp->subsampling_convert_state == sp->subsampling_convert_clines)
- sp->subsampling_convert_state = 0;
- return (1);
- }
- m -= sp->subsampling_convert_clines - sp->subsampling_convert_state;
- sp->subsampling_convert_state = 0;
- sp->error_in_raw_data_decoding = 0;
- }
- while (m >= sp->subsampling_convert_clines)
- {
- if (jpeg_read_raw_data_encap(sp, &(sp->libjpeg_jpeg_decompress_struct),
- sp->subsampling_convert_ycbcrimage,
- sp->subsampling_ver * 8) == 0)
- return (0);
- m -= sp->subsampling_convert_clines;
- }
- if (m > 0)
- {
- if (jpeg_read_raw_data_encap(sp, &(sp->libjpeg_jpeg_decompress_struct),
- sp->subsampling_convert_ycbcrimage,
- sp->subsampling_ver * 8) == 0)
- return (0);
- sp->subsampling_convert_state = m;
- }
- return (1);
- }
- static int OJPEGPreDecodeSkipScanlines(TIFF *tif)
- {
- static const char module[] = "OJPEGPreDecodeSkipScanlines";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint32_t m;
- if (sp->skip_buffer == NULL)
- {
- sp->skip_buffer = _TIFFmallocExt(tif, sp->bytes_per_line);
- if (sp->skip_buffer == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- }
- for (m = 0; m < sp->lines_per_strile; m++)
- {
- if (jpeg_read_scanlines_encap(sp, &(sp->libjpeg_jpeg_decompress_struct),
- &sp->skip_buffer, 1) == 0)
- return (0);
- }
- return (1);
- }
- static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
- {
- static const char module[] = "OJPEGDecode";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- (void)s;
- if (!sp->decoder_ok)
- {
- memset(buf, 0, (size_t)cc);
- TIFFErrorExtR(tif, module,
- "Cannot decode: decoder not correctly initialized");
- return 0;
- }
- if (sp->libjpeg_session_active == 0)
- {
- memset(buf, 0, (size_t)cc);
- /* This should normally not happen, except that it does when */
- /* using TIFFReadScanline() which calls OJPEGPostDecode() for */
- /* each scanline, which assumes that a whole strile was read */
- /* and may thus incorrectly consider it has read the whole image,
- * causing */
- /* OJPEGLibjpegSessionAbort() to be called prematurely. */
- /* Triggered by https://gitlab.com/libtiff/libtiff/-/issues/337 */
- TIFFErrorExtR(tif, module,
- "Cannot decode: libjpeg_session_active == 0");
- return 0;
- }
- if (sp->error_in_raw_data_decoding)
- {
- memset(buf, 0, (size_t)cc);
- return 0;
- }
- if (sp->libjpeg_jpeg_query_style == 0)
- {
- if (OJPEGDecodeRaw(tif, buf, cc) == 0)
- {
- memset(buf, 0, (size_t)cc);
- return (0);
- }
- }
- else
- {
- if (OJPEGDecodeScanlines(tif, buf, cc) == 0)
- {
- memset(buf, 0, (size_t)cc);
- return (0);
- }
- }
- return (1);
- }
- static int OJPEGDecodeRaw(TIFF *tif, uint8_t *buf, tmsize_t cc)
- {
- static const char module[] = "OJPEGDecodeRaw";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t *m;
- tmsize_t n;
- uint8_t *oy;
- uint8_t *ocb;
- uint8_t *ocr;
- uint8_t *p;
- uint32_t q;
- uint8_t *r;
- uint8_t sx, sy;
- if (cc % sp->bytes_per_line != 0)
- {
- TIFFErrorExtR(tif, module, "Fractional scanline not read");
- return (0);
- }
- assert(cc > 0);
- m = buf;
- n = cc;
- do
- {
- if (sp->subsampling_convert_state == 0)
- {
- if (jpeg_read_raw_data_encap(sp,
- &(sp->libjpeg_jpeg_decompress_struct),
- sp->subsampling_convert_ycbcrimage,
- sp->subsampling_ver * 8) == 0)
- {
- sp->error_in_raw_data_decoding = 1;
- return (0);
- }
- }
- oy = sp->subsampling_convert_ybuf +
- sp->subsampling_convert_state * sp->subsampling_ver *
- sp->subsampling_convert_ylinelen;
- ocb = sp->subsampling_convert_cbbuf +
- sp->subsampling_convert_state * sp->subsampling_convert_clinelen;
- ocr = sp->subsampling_convert_crbuf +
- sp->subsampling_convert_state * sp->subsampling_convert_clinelen;
- p = m;
- for (q = 0; q < sp->subsampling_convert_clinelenout; q++)
- {
- r = oy;
- for (sy = 0; sy < sp->subsampling_ver; sy++)
- {
- for (sx = 0; sx < sp->subsampling_hor; sx++)
- *p++ = *r++;
- r += sp->subsampling_convert_ylinelen - sp->subsampling_hor;
- }
- oy += sp->subsampling_hor;
- *p++ = *ocb++;
- *p++ = *ocr++;
- }
- sp->subsampling_convert_state++;
- if (sp->subsampling_convert_state == sp->subsampling_convert_clines)
- sp->subsampling_convert_state = 0;
- m += sp->bytes_per_line;
- n -= sp->bytes_per_line;
- } while (n > 0);
- return (1);
- }
- static int OJPEGDecodeScanlines(TIFF *tif, uint8_t *buf, tmsize_t cc)
- {
- static const char module[] = "OJPEGDecodeScanlines";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t *m;
- tmsize_t n;
- if (cc % sp->bytes_per_line != 0)
- {
- TIFFErrorExtR(tif, module, "Fractional scanline not read");
- return (0);
- }
- assert(cc > 0);
- m = buf;
- n = cc;
- do
- {
- if (jpeg_read_scanlines_encap(sp, &(sp->libjpeg_jpeg_decompress_struct),
- &m, 1) == 0)
- return (0);
- m += sp->bytes_per_line;
- n -= sp->bytes_per_line;
- } while (n > 0);
- return (1);
- }
- static void OJPEGPostDecode(TIFF *tif, uint8_t *buf, tmsize_t cc)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- (void)buf;
- (void)cc;
- /* This function somehow incorrectly assumes that a whole strile was read,
- */
- /* which is not true when TIFFReadScanline() is called, */
- /* and may thus incorrectly consider it has read the whole image, causing */
- /* OJPEGLibjpegSessionAbort() to be called prematurely. */
- /* So this logic should be fixed to take into account cc, or disable */
- /* the scan line reading interface. */
- /* Triggered by https://gitlab.com/libtiff/libtiff/-/issues/337 */
- sp->write_curstrile++;
- if (sp->write_curstrile % tif->tif_dir.td_stripsperimage == 0)
- {
- assert(sp->libjpeg_session_active != 0);
- OJPEGLibjpegSessionAbort(tif);
- sp->writeheader_done = 0;
- }
- }
- static int OJPEGSetupEncode(TIFF *tif)
- {
- static const char module[] = "OJPEGSetupEncode";
- TIFFErrorExtR(
- tif, module,
- "OJPEG encoding not supported; use new-style JPEG compression instead");
- return (0);
- }
- static int OJPEGPreEncode(TIFF *tif, uint16_t s)
- {
- static const char module[] = "OJPEGPreEncode";
- (void)s;
- TIFFErrorExtR(
- tif, module,
- "OJPEG encoding not supported; use new-style JPEG compression instead");
- return (0);
- }
- static int OJPEGEncode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s)
- {
- static const char module[] = "OJPEGEncode";
- (void)buf;
- (void)cc;
- (void)s;
- TIFFErrorExtR(
- tif, module,
- "OJPEG encoding not supported; use new-style JPEG compression instead");
- return (0);
- }
- static int OJPEGPostEncode(TIFF *tif)
- {
- static const char module[] = "OJPEGPostEncode";
- TIFFErrorExtR(
- tif, module,
- "OJPEG encoding not supported; use new-style JPEG compression instead");
- return (0);
- }
- static void OJPEGCleanup(TIFF *tif)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- if (sp != 0)
- {
- tif->tif_tagmethods.vgetfield = sp->vgetparent;
- tif->tif_tagmethods.vsetfield = sp->vsetparent;
- tif->tif_tagmethods.printdir = sp->printdir;
- if (sp->qtable[0] != 0)
- _TIFFfreeExt(tif, sp->qtable[0]);
- if (sp->qtable[1] != 0)
- _TIFFfreeExt(tif, sp->qtable[1]);
- if (sp->qtable[2] != 0)
- _TIFFfreeExt(tif, sp->qtable[2]);
- if (sp->qtable[3] != 0)
- _TIFFfreeExt(tif, sp->qtable[3]);
- if (sp->dctable[0] != 0)
- _TIFFfreeExt(tif, sp->dctable[0]);
- if (sp->dctable[1] != 0)
- _TIFFfreeExt(tif, sp->dctable[1]);
- if (sp->dctable[2] != 0)
- _TIFFfreeExt(tif, sp->dctable[2]);
- if (sp->dctable[3] != 0)
- _TIFFfreeExt(tif, sp->dctable[3]);
- if (sp->actable[0] != 0)
- _TIFFfreeExt(tif, sp->actable[0]);
- if (sp->actable[1] != 0)
- _TIFFfreeExt(tif, sp->actable[1]);
- if (sp->actable[2] != 0)
- _TIFFfreeExt(tif, sp->actable[2]);
- if (sp->actable[3] != 0)
- _TIFFfreeExt(tif, sp->actable[3]);
- if (sp->libjpeg_session_active != 0)
- OJPEGLibjpegSessionAbort(tif);
- if (sp->subsampling_convert_ycbcrbuf != 0)
- _TIFFfreeExt(tif, sp->subsampling_convert_ycbcrbuf);
- if (sp->subsampling_convert_ycbcrimage != 0)
- _TIFFfreeExt(tif, sp->subsampling_convert_ycbcrimage);
- if (sp->skip_buffer != 0)
- _TIFFfreeExt(tif, sp->skip_buffer);
- _TIFFfreeExt(tif, sp);
- tif->tif_data = NULL;
- _TIFFSetDefaultCompressionState(tif);
- }
- }
- static void OJPEGSubsamplingCorrect(TIFF *tif)
- {
- static const char module[] = "OJPEGSubsamplingCorrect";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t mh;
- uint8_t mv;
- assert(sp->subsamplingcorrect_done == 0);
- if ((tif->tif_dir.td_samplesperpixel != 3) ||
- ((tif->tif_dir.td_photometric != PHOTOMETRIC_YCBCR) &&
- (tif->tif_dir.td_photometric != PHOTOMETRIC_ITULAB)))
- {
- if (sp->subsampling_tag != 0)
- TIFFWarningExtR(tif, module,
- "Subsampling tag not appropriate for this "
- "Photometric and/or SamplesPerPixel");
- sp->subsampling_hor = 1;
- sp->subsampling_ver = 1;
- sp->subsampling_force_desubsampling_inside_decompression = 0;
- }
- else
- {
- sp->subsamplingcorrect_done = 1;
- mh = sp->subsampling_hor;
- mv = sp->subsampling_ver;
- sp->subsamplingcorrect = 1;
- OJPEGReadHeaderInfoSec(tif);
- if (sp->subsampling_force_desubsampling_inside_decompression != 0)
- {
- sp->subsampling_hor = 1;
- sp->subsampling_ver = 1;
- }
- sp->subsamplingcorrect = 0;
- if (((sp->subsampling_hor != mh) || (sp->subsampling_ver != mv)) &&
- (sp->subsampling_force_desubsampling_inside_decompression == 0))
- {
- if (sp->subsampling_tag == 0)
- TIFFWarningExtR(
- tif, module,
- "Subsampling tag is not set, yet subsampling inside JPEG "
- "data [%" PRIu8 ",%" PRIu8
- "] does not match default values [2,2]; assuming "
- "subsampling inside JPEG data is correct",
- sp->subsampling_hor, sp->subsampling_ver);
- else
- TIFFWarningExtR(
- tif, module,
- "Subsampling inside JPEG data [%" PRIu8 ",%" PRIu8
- "] does not match subsampling tag values [%" PRIu8
- ",%" PRIu8
- "]; assuming subsampling inside JPEG data is correct",
- sp->subsampling_hor, sp->subsampling_ver, mh, mv);
- }
- if (sp->subsampling_force_desubsampling_inside_decompression != 0)
- {
- if (sp->subsampling_tag == 0)
- TIFFWarningExtR(
- tif, module,
- "Subsampling tag is not set, yet subsampling inside JPEG "
- "data does not match default values [2,2] (nor any other "
- "values allowed in TIFF); assuming subsampling inside JPEG "
- "data is correct and desubsampling inside JPEG "
- "decompression");
- else
- TIFFWarningExtR(
- tif, module,
- "Subsampling inside JPEG data does not match subsampling "
- "tag values [%" PRIu8 ",%" PRIu8
- "] (nor any other values allowed in TIFF); assuming "
- "subsampling inside JPEG data is correct and desubsampling "
- "inside JPEG decompression",
- mh, mv);
- }
- if (sp->subsampling_force_desubsampling_inside_decompression == 0)
- {
- if (sp->subsampling_hor < sp->subsampling_ver)
- TIFFWarningExtR(tif, module,
- "Subsampling values [%" PRIu8 ",%" PRIu8
- "] are not allowed in TIFF",
- sp->subsampling_hor, sp->subsampling_ver);
- }
- }
- sp->subsamplingcorrect_done = 1;
- }
- static int OJPEGReadHeaderInfo(TIFF *tif)
- {
- static const char module[] = "OJPEGReadHeaderInfo";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- assert(sp->readheader_done == 0);
- sp->image_width = tif->tif_dir.td_imagewidth;
- sp->image_length = tif->tif_dir.td_imagelength;
- if (isTiled(tif))
- {
- sp->strile_width = tif->tif_dir.td_tilewidth;
- sp->strile_length = tif->tif_dir.td_tilelength;
- sp->strile_length_total =
- ((sp->image_length + sp->strile_length - 1) / sp->strile_length) *
- sp->strile_length;
- }
- else
- {
- sp->strile_width = sp->image_width;
- sp->strile_length = tif->tif_dir.td_rowsperstrip;
- if (sp->strile_length == (uint32_t)-1)
- sp->strile_length = sp->image_length;
- sp->strile_length_total = sp->image_length;
- }
- if (tif->tif_dir.td_samplesperpixel == 1)
- {
- sp->samples_per_pixel = 1;
- sp->plane_sample_offset = 0;
- sp->samples_per_pixel_per_plane = sp->samples_per_pixel;
- sp->subsampling_hor = 1;
- sp->subsampling_ver = 1;
- }
- else
- {
- if (tif->tif_dir.td_samplesperpixel != 3)
- {
- TIFFErrorExtR(tif, module,
- "SamplesPerPixel %" PRIu8
- " not supported for this compression scheme",
- sp->samples_per_pixel);
- return (0);
- }
- sp->samples_per_pixel = 3;
- sp->plane_sample_offset = 0;
- if (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG)
- sp->samples_per_pixel_per_plane = 3;
- else
- sp->samples_per_pixel_per_plane = 1;
- }
- if (sp->strile_length < sp->image_length)
- {
- if (((sp->subsampling_hor != 1) && (sp->subsampling_hor != 2) &&
- (sp->subsampling_hor != 4)) ||
- ((sp->subsampling_ver != 1) && (sp->subsampling_ver != 2) &&
- (sp->subsampling_ver != 4)))
- {
- TIFFErrorExtR(tif, module, "Invalid subsampling values");
- return (0);
- }
- if (sp->strile_length % (sp->subsampling_ver * 8) != 0)
- {
- TIFFErrorExtR(tif, module,
- "Incompatible vertical subsampling and image "
- "strip/tile length");
- return (0);
- }
- sp->restart_interval =
- (uint16_t)(((sp->strile_width + sp->subsampling_hor * 8 - 1) /
- (sp->subsampling_hor * 8)) *
- (sp->strile_length / (sp->subsampling_ver * 8)));
- }
- if (OJPEGReadHeaderInfoSec(tif) == 0)
- return (0);
- sp->sos_end[0].log = 1;
- sp->sos_end[0].in_buffer_source = sp->in_buffer_source;
- sp->sos_end[0].in_buffer_next_strile = sp->in_buffer_next_strile;
- sp->sos_end[0].in_buffer_file_pos =
- sp->in_buffer_file_pos - sp->in_buffer_togo;
- sp->sos_end[0].in_buffer_file_togo =
- sp->in_buffer_file_togo + sp->in_buffer_togo;
- sp->readheader_done = 1;
- return (1);
- }
- static int OJPEGReadSecondarySos(TIFF *tif, uint16_t s)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t m;
- assert(s > 0);
- assert(s < 3);
- assert(sp->sos_end[0].log != 0);
- assert(sp->sos_end[s].log == 0);
- sp->plane_sample_offset = (uint8_t)(s - 1);
- while (sp->sos_end[sp->plane_sample_offset].log == 0)
- sp->plane_sample_offset--;
- sp->in_buffer_source =
- sp->sos_end[sp->plane_sample_offset].in_buffer_source;
- sp->in_buffer_next_strile =
- sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile;
- sp->in_buffer_file_pos =
- sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos;
- sp->in_buffer_file_pos_log = 0;
- sp->in_buffer_file_togo =
- sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo;
- sp->in_buffer_togo = 0;
- sp->in_buffer_cur = 0;
- while (sp->plane_sample_offset < s)
- {
- do
- {
- if (OJPEGReadByte(sp, &m) == 0)
- return (0);
- if (m == 255)
- {
- do
- {
- if (OJPEGReadByte(sp, &m) == 0)
- return (0);
- if (m != 255)
- break;
- } while (1);
- if (m == JPEG_MARKER_SOS)
- break;
- }
- } while (1);
- sp->plane_sample_offset++;
- if (OJPEGReadHeaderInfoSecStreamSos(tif) == 0)
- return (0);
- sp->sos_end[sp->plane_sample_offset].log = 1;
- sp->sos_end[sp->plane_sample_offset].in_buffer_source =
- sp->in_buffer_source;
- sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile =
- sp->in_buffer_next_strile;
- sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos =
- sp->in_buffer_file_pos - sp->in_buffer_togo;
- sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo =
- sp->in_buffer_file_togo + sp->in_buffer_togo;
- }
- return (1);
- }
- static int OJPEGWriteHeaderInfo(TIFF *tif)
- {
- static const char module[] = "OJPEGWriteHeaderInfo";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t **m;
- uint32_t n;
- /* if a previous attempt failed, don't try again */
- if (sp->libjpeg_session_active != 0)
- return 0;
- sp->out_state = ososSoi;
- sp->restart_index = 0;
- jpeg_std_error(&(sp->libjpeg_jpeg_error_mgr));
- sp->libjpeg_jpeg_error_mgr.output_message =
- OJPEGLibjpegJpegErrorMgrOutputMessage;
- sp->libjpeg_jpeg_error_mgr.error_exit = OJPEGLibjpegJpegErrorMgrErrorExit;
- sp->libjpeg_jpeg_decompress_struct.err = &(sp->libjpeg_jpeg_error_mgr);
- sp->libjpeg_jpeg_decompress_struct.client_data = (void *)tif;
- if (jpeg_create_decompress_encap(
- sp, &(sp->libjpeg_jpeg_decompress_struct)) == 0)
- return (0);
- sp->libjpeg_session_active = 1;
- sp->libjpeg_jpeg_source_mgr.bytes_in_buffer = 0;
- sp->libjpeg_jpeg_source_mgr.init_source =
- OJPEGLibjpegJpegSourceMgrInitSource;
- sp->libjpeg_jpeg_source_mgr.fill_input_buffer =
- OJPEGLibjpegJpegSourceMgrFillInputBuffer;
- sp->libjpeg_jpeg_source_mgr.skip_input_data =
- OJPEGLibjpegJpegSourceMgrSkipInputData;
- sp->libjpeg_jpeg_source_mgr.resync_to_restart =
- OJPEGLibjpegJpegSourceMgrResyncToRestart;
- sp->libjpeg_jpeg_source_mgr.term_source =
- OJPEGLibjpegJpegSourceMgrTermSource;
- sp->libjpeg_jpeg_decompress_struct.src = &(sp->libjpeg_jpeg_source_mgr);
- if (jpeg_read_header_encap(sp, &(sp->libjpeg_jpeg_decompress_struct), 1) ==
- 0)
- return (0);
- if ((sp->subsampling_force_desubsampling_inside_decompression == 0) &&
- (sp->samples_per_pixel_per_plane > 1))
- {
- sp->libjpeg_jpeg_decompress_struct.raw_data_out = 1;
- #if JPEG_LIB_VERSION >= 70
- sp->libjpeg_jpeg_decompress_struct.do_fancy_upsampling = FALSE;
- #endif
- sp->libjpeg_jpeg_query_style = 0;
- if (sp->subsampling_convert_log == 0)
- {
- assert(sp->subsampling_convert_ycbcrbuf == 0);
- assert(sp->subsampling_convert_ycbcrimage == 0);
- /* Check for division by zero. */
- if (sp->subsampling_hor == 0 || sp->subsampling_ver == 0)
- return (0);
- sp->subsampling_convert_ylinelen =
- ((sp->strile_width + sp->subsampling_hor * 8 - 1) /
- (sp->subsampling_hor * 8) * sp->subsampling_hor * 8);
- sp->subsampling_convert_ylines = sp->subsampling_ver * 8;
- sp->subsampling_convert_clinelen =
- sp->subsampling_convert_ylinelen / sp->subsampling_hor;
- sp->subsampling_convert_clines = 8;
- sp->subsampling_convert_ybuflen = sp->subsampling_convert_ylinelen *
- sp->subsampling_convert_ylines;
- sp->subsampling_convert_cbuflen = sp->subsampling_convert_clinelen *
- sp->subsampling_convert_clines;
- sp->subsampling_convert_ycbcrbuflen =
- sp->subsampling_convert_ybuflen +
- 2 * sp->subsampling_convert_cbuflen;
- /* The calloc is not normally necessary, except in some edge/broken
- * cases */
- /* for example for a tiled image of height 1 with a tile height of 1
- * and subsampling_hor=subsampling_ver=2 */
- /* In that case, libjpeg will only fill the 8 first lines of the 16
- * lines */
- /* See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16844
- */
- /* Even if this case is allowed (?), its handling is broken because
- * OJPEGPreDecode() should also likely */
- /* reset subsampling_convert_state to 0 when changing tile. */
- sp->subsampling_convert_ycbcrbuf =
- _TIFFcallocExt(tif, 1, sp->subsampling_convert_ycbcrbuflen);
- if (sp->subsampling_convert_ycbcrbuf == 0)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- sp->subsampling_convert_ybuf = sp->subsampling_convert_ycbcrbuf;
- sp->subsampling_convert_cbbuf =
- sp->subsampling_convert_ybuf + sp->subsampling_convert_ybuflen;
- sp->subsampling_convert_crbuf =
- sp->subsampling_convert_cbbuf + sp->subsampling_convert_cbuflen;
- sp->subsampling_convert_ycbcrimagelen =
- 3 + sp->subsampling_convert_ylines +
- 2 * sp->subsampling_convert_clines;
- sp->subsampling_convert_ycbcrimage = _TIFFmallocExt(
- tif, sp->subsampling_convert_ycbcrimagelen * sizeof(uint8_t *));
- if (sp->subsampling_convert_ycbcrimage == 0)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- m = sp->subsampling_convert_ycbcrimage;
- *m++ = (uint8_t *)(sp->subsampling_convert_ycbcrimage + 3);
- *m++ = (uint8_t *)(sp->subsampling_convert_ycbcrimage + 3 +
- sp->subsampling_convert_ylines);
- *m++ = (uint8_t *)(sp->subsampling_convert_ycbcrimage + 3 +
- sp->subsampling_convert_ylines +
- sp->subsampling_convert_clines);
- for (n = 0; n < sp->subsampling_convert_ylines; n++)
- *m++ = sp->subsampling_convert_ybuf +
- n * sp->subsampling_convert_ylinelen;
- for (n = 0; n < sp->subsampling_convert_clines; n++)
- *m++ = sp->subsampling_convert_cbbuf +
- n * sp->subsampling_convert_clinelen;
- for (n = 0; n < sp->subsampling_convert_clines; n++)
- *m++ = sp->subsampling_convert_crbuf +
- n * sp->subsampling_convert_clinelen;
- sp->subsampling_convert_clinelenout =
- sp->strile_width / sp->subsampling_hor +
- ((sp->strile_width % sp->subsampling_hor) != 0 ? 1 : 0);
- sp->subsampling_convert_state = 0;
- sp->error_in_raw_data_decoding = 0;
- sp->bytes_per_line =
- sp->subsampling_convert_clinelenout *
- (sp->subsampling_ver * sp->subsampling_hor + 2);
- sp->lines_per_strile =
- sp->strile_length / sp->subsampling_ver +
- ((sp->strile_length % sp->subsampling_ver) != 0 ? 1 : 0);
- sp->subsampling_convert_log = 1;
- }
- }
- else
- {
- sp->libjpeg_jpeg_decompress_struct.jpeg_color_space = JCS_UNKNOWN;
- sp->libjpeg_jpeg_decompress_struct.out_color_space = JCS_UNKNOWN;
- sp->libjpeg_jpeg_query_style = 1;
- sp->bytes_per_line = sp->samples_per_pixel_per_plane * sp->strile_width;
- sp->lines_per_strile = sp->strile_length;
- }
- if (jpeg_start_decompress_encap(sp,
- &(sp->libjpeg_jpeg_decompress_struct)) == 0)
- return (0);
- if (sp->libjpeg_jpeg_decompress_struct.image_width != sp->strile_width)
- {
- TIFFErrorExtR(tif, module,
- "jpeg_start_decompress() returned image_width = %u, "
- "expected %" PRIu32,
- sp->libjpeg_jpeg_decompress_struct.image_width,
- sp->strile_width);
- return 0;
- }
- if (sp->libjpeg_jpeg_decompress_struct.max_h_samp_factor !=
- sp->subsampling_hor ||
- sp->libjpeg_jpeg_decompress_struct.max_v_samp_factor !=
- sp->subsampling_ver)
- {
- TIFFErrorExtR(tif, module,
- "jpeg_start_decompress() returned max_h_samp_factor = %d "
- "and max_v_samp_factor = %d, expected %" PRIu8
- " and %" PRIu8,
- sp->libjpeg_jpeg_decompress_struct.max_h_samp_factor,
- sp->libjpeg_jpeg_decompress_struct.max_v_samp_factor,
- sp->subsampling_hor, sp->subsampling_ver);
- return 0;
- }
- sp->writeheader_done = 1;
- return (1);
- }
- static void OJPEGLibjpegSessionAbort(TIFF *tif)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- assert(sp->libjpeg_session_active != 0);
- jpeg_destroy((jpeg_common_struct *)(&(sp->libjpeg_jpeg_decompress_struct)));
- sp->libjpeg_session_active = 0;
- }
- static int OJPEGReadHeaderInfoSec(TIFF *tif)
- {
- static const char module[] = "OJPEGReadHeaderInfoSec";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t m;
- uint16_t n;
- uint8_t o;
- if (sp->file_size == 0)
- sp->file_size = TIFFGetFileSize(tif);
- if (sp->jpeg_interchange_format != 0)
- {
- if (sp->jpeg_interchange_format >= sp->file_size)
- {
- sp->jpeg_interchange_format = 0;
- sp->jpeg_interchange_format_length = 0;
- }
- else
- {
- if ((sp->jpeg_interchange_format_length == 0) ||
- (sp->jpeg_interchange_format >
- UINT64_MAX - sp->jpeg_interchange_format_length) ||
- (sp->jpeg_interchange_format +
- sp->jpeg_interchange_format_length >
- sp->file_size))
- sp->jpeg_interchange_format_length =
- sp->file_size - sp->jpeg_interchange_format;
- }
- }
- sp->in_buffer_source = osibsNotSetYet;
- sp->in_buffer_next_strile = 0;
- sp->in_buffer_strile_count = tif->tif_dir.td_nstrips;
- sp->in_buffer_file_togo = 0;
- sp->in_buffer_togo = 0;
- do
- {
- if (OJPEGReadBytePeek(sp, &m) == 0)
- return (0);
- if (m != 255)
- break;
- OJPEGReadByteAdvance(sp);
- do
- {
- if (OJPEGReadByte(sp, &m) == 0)
- return (0);
- } while (m == 255);
- switch (m)
- {
- case JPEG_MARKER_SOI:
- /* this type of marker has no data, and should be skipped */
- break;
- case JPEG_MARKER_COM:
- case JPEG_MARKER_APP0:
- case JPEG_MARKER_APP0 + 1:
- case JPEG_MARKER_APP0 + 2:
- case JPEG_MARKER_APP0 + 3:
- case JPEG_MARKER_APP0 + 4:
- case JPEG_MARKER_APP0 + 5:
- case JPEG_MARKER_APP0 + 6:
- case JPEG_MARKER_APP0 + 7:
- case JPEG_MARKER_APP0 + 8:
- case JPEG_MARKER_APP0 + 9:
- case JPEG_MARKER_APP0 + 10:
- case JPEG_MARKER_APP0 + 11:
- case JPEG_MARKER_APP0 + 12:
- case JPEG_MARKER_APP0 + 13:
- case JPEG_MARKER_APP0 + 14:
- case JPEG_MARKER_APP0 + 15:
- /* this type of marker has data, but it has no use to us (and no
- * place here) and should be skipped */
- if (OJPEGReadWord(sp, &n) == 0)
- return (0);
- if (n < 2)
- {
- if (sp->subsamplingcorrect == 0)
- TIFFErrorExtR(tif, module, "Corrupt JPEG data");
- return (0);
- }
- if (n > 2)
- OJPEGReadSkip(sp, n - 2);
- break;
- case JPEG_MARKER_DRI:
- if (OJPEGReadHeaderInfoSecStreamDri(tif) == 0)
- return (0);
- break;
- case JPEG_MARKER_DQT:
- if (OJPEGReadHeaderInfoSecStreamDqt(tif) == 0)
- return (0);
- break;
- case JPEG_MARKER_DHT:
- if (OJPEGReadHeaderInfoSecStreamDht(tif) == 0)
- return (0);
- break;
- case JPEG_MARKER_SOF0:
- case JPEG_MARKER_SOF1:
- case JPEG_MARKER_SOF3:
- if (OJPEGReadHeaderInfoSecStreamSof(tif, m) == 0)
- return (0);
- if (sp->subsamplingcorrect != 0)
- return (1);
- break;
- case JPEG_MARKER_SOS:
- if (sp->subsamplingcorrect != 0)
- return (1);
- assert(sp->plane_sample_offset == 0);
- if (OJPEGReadHeaderInfoSecStreamSos(tif) == 0)
- return (0);
- break;
- default:
- TIFFErrorExtR(tif, module,
- "Unknown marker type %" PRIu8 " in JPEG data", m);
- return (0);
- }
- } while (m != JPEG_MARKER_SOS);
- if (sp->subsamplingcorrect)
- return (1);
- if (sp->sof_log == 0)
- {
- if (OJPEGReadHeaderInfoSecTablesQTable(tif) == 0)
- return (0);
- sp->sof_marker_id = JPEG_MARKER_SOF0;
- for (o = 0; o < sp->samples_per_pixel; o++)
- sp->sof_c[o] = o;
- sp->sof_hv[0] = ((sp->subsampling_hor << 4) | sp->subsampling_ver);
- for (o = 1; o < sp->samples_per_pixel; o++)
- sp->sof_hv[o] = 17;
- sp->sof_x = sp->strile_width;
- sp->sof_y = sp->strile_length_total;
- sp->sof_log = 1;
- if (OJPEGReadHeaderInfoSecTablesDcTable(tif) == 0)
- return (0);
- if (OJPEGReadHeaderInfoSecTablesAcTable(tif) == 0)
- return (0);
- for (o = 1; o < sp->samples_per_pixel; o++)
- sp->sos_cs[o] = o;
- }
- return (1);
- }
- static int OJPEGReadHeaderInfoSecStreamDri(TIFF *tif)
- {
- /* This could easily cause trouble in some cases... but no such cases have
- occurred so far */
- static const char module[] = "OJPEGReadHeaderInfoSecStreamDri";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint16_t m;
- if (OJPEGReadWord(sp, &m) == 0)
- return (0);
- if (m != 4)
- {
- TIFFErrorExtR(tif, module, "Corrupt DRI marker in JPEG data");
- return (0);
- }
- if (OJPEGReadWord(sp, &m) == 0)
- return (0);
- sp->restart_interval = m;
- return (1);
- }
- static int OJPEGReadHeaderInfoSecStreamDqt(TIFF *tif)
- {
- /* this is a table marker, and it is to be saved as a whole for exact
- * pushing on the jpeg stream later on */
- static const char module[] = "OJPEGReadHeaderInfoSecStreamDqt";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint16_t m;
- uint32_t na;
- uint8_t *nb;
- uint8_t o;
- if (OJPEGReadWord(sp, &m) == 0)
- return (0);
- if (m <= 2)
- {
- if (sp->subsamplingcorrect == 0)
- TIFFErrorExtR(tif, module, "Corrupt DQT marker in JPEG data");
- return (0);
- }
- if (sp->subsamplingcorrect != 0)
- OJPEGReadSkip(sp, m - 2);
- else
- {
- m -= 2;
- do
- {
- if (m < 65)
- {
- TIFFErrorExtR(tif, module, "Corrupt DQT marker in JPEG data");
- return (0);
- }
- na = sizeof(uint32_t) + 69;
- nb = _TIFFmallocExt(tif, na);
- if (nb == 0)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- *(uint32_t *)nb = na;
- nb[sizeof(uint32_t)] = 255;
- nb[sizeof(uint32_t) + 1] = JPEG_MARKER_DQT;
- nb[sizeof(uint32_t) + 2] = 0;
- nb[sizeof(uint32_t) + 3] = 67;
- if (OJPEGReadBlock(sp, 65, &nb[sizeof(uint32_t) + 4]) == 0)
- {
- _TIFFfreeExt(tif, nb);
- return (0);
- }
- o = nb[sizeof(uint32_t) + 4] & 15;
- if (3 < o)
- {
- TIFFErrorExtR(tif, module, "Corrupt DQT marker in JPEG data");
- _TIFFfreeExt(tif, nb);
- return (0);
- }
- if (sp->qtable[o] != 0)
- _TIFFfreeExt(tif, sp->qtable[o]);
- sp->qtable[o] = nb;
- m -= 65;
- } while (m > 0);
- }
- return (1);
- }
- static int OJPEGReadHeaderInfoSecStreamDht(TIFF *tif)
- {
- /* this is a table marker, and it is to be saved as a whole for exact
- * pushing on the jpeg stream later on */
- /* TODO: the following assumes there is only one table in this marker... but
- * i'm not quite sure that assumption is guaranteed correct */
- static const char module[] = "OJPEGReadHeaderInfoSecStreamDht";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint16_t m;
- uint32_t na;
- uint8_t *nb;
- uint8_t o;
- if (OJPEGReadWord(sp, &m) == 0)
- return (0);
- if (m <= 2)
- {
- if (sp->subsamplingcorrect == 0)
- TIFFErrorExtR(tif, module, "Corrupt DHT marker in JPEG data");
- return (0);
- }
- if (sp->subsamplingcorrect != 0)
- {
- OJPEGReadSkip(sp, m - 2);
- }
- else
- {
- na = sizeof(uint32_t) + 2 + m;
- nb = _TIFFmallocExt(tif, na);
- if (nb == 0)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- *(uint32_t *)nb = na;
- nb[sizeof(uint32_t)] = 255;
- nb[sizeof(uint32_t) + 1] = JPEG_MARKER_DHT;
- nb[sizeof(uint32_t) + 2] = (m >> 8);
- nb[sizeof(uint32_t) + 3] = (m & 255);
- if (OJPEGReadBlock(sp, m - 2, &nb[sizeof(uint32_t) + 4]) == 0)
- {
- _TIFFfreeExt(tif, nb);
- return (0);
- }
- o = nb[sizeof(uint32_t) + 4];
- if ((o & 240) == 0)
- {
- if (3 < o)
- {
- TIFFErrorExtR(tif, module, "Corrupt DHT marker in JPEG data");
- _TIFFfreeExt(tif, nb);
- return (0);
- }
- if (sp->dctable[o] != 0)
- _TIFFfreeExt(tif, sp->dctable[o]);
- sp->dctable[o] = nb;
- }
- else
- {
- if ((o & 240) != 16)
- {
- TIFFErrorExtR(tif, module, "Corrupt DHT marker in JPEG data");
- _TIFFfreeExt(tif, nb);
- return (0);
- }
- o &= 15;
- if (3 < o)
- {
- TIFFErrorExtR(tif, module, "Corrupt DHT marker in JPEG data");
- _TIFFfreeExt(tif, nb);
- return (0);
- }
- if (sp->actable[o] != 0)
- _TIFFfreeExt(tif, sp->actable[o]);
- sp->actable[o] = nb;
- }
- }
- return (1);
- }
- static int OJPEGReadHeaderInfoSecStreamSof(TIFF *tif, uint8_t marker_id)
- {
- /* this marker needs to be checked, and part of its data needs to be saved
- * for regeneration later on */
- static const char module[] = "OJPEGReadHeaderInfoSecStreamSof";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint16_t m;
- uint16_t n;
- uint8_t o;
- uint16_t p;
- uint16_t q;
- if (sp->sof_log != 0)
- {
- TIFFErrorExtR(tif, module, "Corrupt JPEG data");
- return (0);
- }
- if (sp->subsamplingcorrect == 0)
- sp->sof_marker_id = marker_id;
- /* Lf: data length */
- if (OJPEGReadWord(sp, &m) == 0)
- return (0);
- if (m < 11)
- {
- if (sp->subsamplingcorrect == 0)
- TIFFErrorExtR(tif, module, "Corrupt SOF marker in JPEG data");
- return (0);
- }
- m -= 8;
- if (m % 3 != 0)
- {
- if (sp->subsamplingcorrect == 0)
- TIFFErrorExtR(tif, module, "Corrupt SOF marker in JPEG data");
- return (0);
- }
- n = m / 3;
- if (sp->subsamplingcorrect == 0)
- {
- if (n != sp->samples_per_pixel)
- {
- TIFFErrorExtR(
- tif, module,
- "JPEG compressed data indicates unexpected number of samples");
- return (0);
- }
- }
- /* P: Sample precision */
- if (OJPEGReadByte(sp, &o) == 0)
- return (0);
- if (o != 8)
- {
- if (sp->subsamplingcorrect == 0)
- TIFFErrorExtR(tif, module,
- "JPEG compressed data indicates unexpected number of "
- "bits per sample");
- return (0);
- }
- /* Y: Number of lines, X: Number of samples per line */
- if (sp->subsamplingcorrect)
- OJPEGReadSkip(sp, 4);
- else
- {
- /* Y: Number of lines */
- if (OJPEGReadWord(sp, &p) == 0)
- return (0);
- if (((uint32_t)p < sp->image_length) &&
- ((uint32_t)p < sp->strile_length_total))
- {
- TIFFErrorExtR(tif, module,
- "JPEG compressed data indicates unexpected height");
- return (0);
- }
- sp->sof_y = p;
- /* X: Number of samples per line */
- if (OJPEGReadWord(sp, &p) == 0)
- return (0);
- if (((uint32_t)p < sp->image_width) && ((uint32_t)p < sp->strile_width))
- {
- TIFFErrorExtR(tif, module,
- "JPEG compressed data indicates unexpected width");
- return (0);
- }
- if ((uint32_t)p > sp->strile_width)
- {
- TIFFErrorExtR(tif, module,
- "JPEG compressed data image width exceeds expected "
- "image width");
- return (0);
- }
- sp->sof_x = p;
- }
- /* Nf: Number of image components in frame */
- if (OJPEGReadByte(sp, &o) == 0)
- return (0);
- if (o != n)
- {
- if (sp->subsamplingcorrect == 0)
- TIFFErrorExtR(tif, module, "Corrupt SOF marker in JPEG data");
- return (0);
- }
- /* per component stuff */
- /* TODO: double-check that flow implies that n cannot be as big as to make
- * us overflow sof_c, sof_hv and sof_tq arrays */
- for (q = 0; q < n; q++)
- {
- /* C: Component identifier */
- if (OJPEGReadByte(sp, &o) == 0)
- return (0);
- if (sp->subsamplingcorrect == 0)
- sp->sof_c[q] = o;
- /* H: Horizontal sampling factor, and V: Vertical sampling factor */
- if (OJPEGReadByte(sp, &o) == 0)
- return (0);
- if (sp->subsamplingcorrect != 0)
- {
- if (q == 0)
- {
- sp->subsampling_hor = (o >> 4);
- sp->subsampling_ver = (o & 15);
- if (((sp->subsampling_hor != 1) && (sp->subsampling_hor != 2) &&
- (sp->subsampling_hor != 4)) ||
- ((sp->subsampling_ver != 1) && (sp->subsampling_ver != 2) &&
- (sp->subsampling_ver != 4)))
- sp->subsampling_force_desubsampling_inside_decompression =
- 1;
- }
- else
- {
- if (o != 17)
- sp->subsampling_force_desubsampling_inside_decompression =
- 1;
- }
- }
- else
- {
- sp->sof_hv[q] = o;
- if (sp->subsampling_force_desubsampling_inside_decompression == 0)
- {
- if (q == 0)
- {
- if (o != ((sp->subsampling_hor << 4) | sp->subsampling_ver))
- {
- TIFFErrorExtR(tif, module,
- "JPEG compressed data indicates "
- "unexpected subsampling values");
- return (0);
- }
- }
- else
- {
- if (o != 17)
- {
- TIFFErrorExtR(tif, module,
- "JPEG compressed data indicates "
- "unexpected subsampling values");
- return (0);
- }
- }
- }
- }
- /* Tq: Quantization table destination selector */
- if (OJPEGReadByte(sp, &o) == 0)
- return (0);
- if (sp->subsamplingcorrect == 0)
- sp->sof_tq[q] = o;
- }
- if (sp->subsamplingcorrect == 0)
- sp->sof_log = 1;
- return (1);
- }
- static int OJPEGReadHeaderInfoSecStreamSos(TIFF *tif)
- {
- /* this marker needs to be checked, and part of its data needs to be saved
- * for regeneration later on */
- static const char module[] = "OJPEGReadHeaderInfoSecStreamSos";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint16_t m;
- uint8_t n;
- uint8_t o;
- assert(sp->subsamplingcorrect == 0);
- if (sp->sof_log == 0)
- {
- TIFFErrorExtR(tif, module, "Corrupt SOS marker in JPEG data");
- return (0);
- }
- /* Ls */
- if (OJPEGReadWord(sp, &m) == 0)
- return (0);
- if (m != 6 + sp->samples_per_pixel_per_plane * 2)
- {
- TIFFErrorExtR(tif, module, "Corrupt SOS marker in JPEG data");
- return (0);
- }
- /* Ns */
- if (OJPEGReadByte(sp, &n) == 0)
- return (0);
- if (n != sp->samples_per_pixel_per_plane)
- {
- TIFFErrorExtR(tif, module, "Corrupt SOS marker in JPEG data");
- return (0);
- }
- /* Cs, Td, and Ta */
- for (o = 0; o < sp->samples_per_pixel_per_plane; o++)
- {
- /* Cs */
- if (OJPEGReadByte(sp, &n) == 0)
- return (0);
- sp->sos_cs[sp->plane_sample_offset + o] = n;
- /* Td and Ta */
- if (OJPEGReadByte(sp, &n) == 0)
- return (0);
- sp->sos_tda[sp->plane_sample_offset + o] = n;
- }
- /* skip Ss, Se, Ah, en Al -> no check, as per Tom Lane recommendation, as
- * per LibJpeg source */
- OJPEGReadSkip(sp, 3);
- return (1);
- }
- static int OJPEGReadHeaderInfoSecTablesQTable(TIFF *tif)
- {
- static const char module[] = "OJPEGReadHeaderInfoSecTablesQTable";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t m;
- uint8_t n;
- uint32_t oa;
- uint8_t *ob;
- uint32_t p;
- if (sp->qtable_offset[0] == 0)
- {
- TIFFErrorExtR(tif, module, "Missing JPEG tables");
- return (0);
- }
- sp->in_buffer_file_pos_log = 0;
- for (m = 0; m < sp->samples_per_pixel; m++)
- {
- if ((sp->qtable_offset[m] != 0) &&
- ((m == 0) || (sp->qtable_offset[m] != sp->qtable_offset[m - 1])))
- {
- for (n = 0; n < m - 1; n++)
- {
- if (sp->qtable_offset[m] == sp->qtable_offset[n])
- {
- TIFFErrorExtR(tif, module, "Corrupt JpegQTables tag value");
- return (0);
- }
- }
- oa = sizeof(uint32_t) + 69;
- ob = _TIFFmallocExt(tif, oa);
- if (ob == 0)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- *(uint32_t *)ob = oa;
- ob[sizeof(uint32_t)] = 255;
- ob[sizeof(uint32_t) + 1] = JPEG_MARKER_DQT;
- ob[sizeof(uint32_t) + 2] = 0;
- ob[sizeof(uint32_t) + 3] = 67;
- ob[sizeof(uint32_t) + 4] = m;
- TIFFSeekFile(tif, sp->qtable_offset[m], SEEK_SET);
- p = (uint32_t)TIFFReadFile(tif, &ob[sizeof(uint32_t) + 5], 64);
- if (p != 64)
- {
- _TIFFfreeExt(tif, ob);
- return (0);
- }
- if (sp->qtable[m] != 0)
- _TIFFfreeExt(tif, sp->qtable[m]);
- sp->qtable[m] = ob;
- sp->sof_tq[m] = m;
- }
- else
- sp->sof_tq[m] = sp->sof_tq[m - 1];
- }
- return (1);
- }
- static int OJPEGReadHeaderInfoSecTablesDcTable(TIFF *tif)
- {
- static const char module[] = "OJPEGReadHeaderInfoSecTablesDcTable";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t m;
- uint8_t n;
- uint8_t o[16];
- uint32_t p;
- uint32_t q;
- uint32_t ra;
- uint8_t *rb;
- if (sp->dctable_offset[0] == 0)
- {
- TIFFErrorExtR(tif, module, "Missing JPEG tables");
- return (0);
- }
- sp->in_buffer_file_pos_log = 0;
- for (m = 0; m < sp->samples_per_pixel; m++)
- {
- if ((sp->dctable_offset[m] != 0) &&
- ((m == 0) || (sp->dctable_offset[m] != sp->dctable_offset[m - 1])))
- {
- for (n = 0; n < m - 1; n++)
- {
- if (sp->dctable_offset[m] == sp->dctable_offset[n])
- {
- TIFFErrorExtR(tif, module,
- "Corrupt JpegDcTables tag value");
- return (0);
- }
- }
- TIFFSeekFile(tif, sp->dctable_offset[m], SEEK_SET);
- p = (uint32_t)TIFFReadFile(tif, o, 16);
- if (p != 16)
- return (0);
- q = 0;
- for (n = 0; n < 16; n++)
- q += o[n];
- ra = sizeof(uint32_t) + 21 + q;
- rb = _TIFFmallocExt(tif, ra);
- if (rb == 0)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- *(uint32_t *)rb = ra;
- rb[sizeof(uint32_t)] = 255;
- rb[sizeof(uint32_t) + 1] = JPEG_MARKER_DHT;
- rb[sizeof(uint32_t) + 2] = (uint8_t)((19 + q) >> 8);
- rb[sizeof(uint32_t) + 3] = ((19 + q) & 255);
- rb[sizeof(uint32_t) + 4] = m;
- for (n = 0; n < 16; n++)
- rb[sizeof(uint32_t) + 5 + n] = o[n];
- p = (uint32_t)TIFFReadFile(tif, &(rb[sizeof(uint32_t) + 21]), q);
- if (p != q)
- {
- _TIFFfreeExt(tif, rb);
- return (0);
- }
- if (sp->dctable[m] != 0)
- _TIFFfreeExt(tif, sp->dctable[m]);
- sp->dctable[m] = rb;
- sp->sos_tda[m] = (m << 4);
- }
- else
- sp->sos_tda[m] = sp->sos_tda[m - 1];
- }
- return (1);
- }
- static int OJPEGReadHeaderInfoSecTablesAcTable(TIFF *tif)
- {
- static const char module[] = "OJPEGReadHeaderInfoSecTablesAcTable";
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t m;
- uint8_t n;
- uint8_t o[16];
- uint32_t p;
- uint32_t q;
- uint32_t ra;
- uint8_t *rb;
- if (sp->actable_offset[0] == 0)
- {
- TIFFErrorExtR(tif, module, "Missing JPEG tables");
- return (0);
- }
- sp->in_buffer_file_pos_log = 0;
- for (m = 0; m < sp->samples_per_pixel; m++)
- {
- if ((sp->actable_offset[m] != 0) &&
- ((m == 0) || (sp->actable_offset[m] != sp->actable_offset[m - 1])))
- {
- for (n = 0; n < m - 1; n++)
- {
- if (sp->actable_offset[m] == sp->actable_offset[n])
- {
- TIFFErrorExtR(tif, module,
- "Corrupt JpegAcTables tag value");
- return (0);
- }
- }
- TIFFSeekFile(tif, sp->actable_offset[m], SEEK_SET);
- p = (uint32_t)TIFFReadFile(tif, o, 16);
- if (p != 16)
- return (0);
- q = 0;
- for (n = 0; n < 16; n++)
- q += o[n];
- ra = sizeof(uint32_t) + 21 + q;
- rb = _TIFFmallocExt(tif, ra);
- if (rb == 0)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- *(uint32_t *)rb = ra;
- rb[sizeof(uint32_t)] = 255;
- rb[sizeof(uint32_t) + 1] = JPEG_MARKER_DHT;
- rb[sizeof(uint32_t) + 2] = (uint8_t)((19 + q) >> 8);
- rb[sizeof(uint32_t) + 3] = ((19 + q) & 255);
- rb[sizeof(uint32_t) + 4] = (16 | m);
- for (n = 0; n < 16; n++)
- rb[sizeof(uint32_t) + 5 + n] = o[n];
- p = (uint32_t)TIFFReadFile(tif, &(rb[sizeof(uint32_t) + 21]), q);
- if (p != q)
- {
- _TIFFfreeExt(tif, rb);
- return (0);
- }
- if (sp->actable[m] != 0)
- _TIFFfreeExt(tif, sp->actable[m]);
- sp->actable[m] = rb;
- sp->sos_tda[m] = (sp->sos_tda[m] | m);
- }
- else
- sp->sos_tda[m] = (sp->sos_tda[m] | (sp->sos_tda[m - 1] & 15));
- }
- return (1);
- }
- static int OJPEGReadBufferFill(OJPEGState *sp)
- {
- uint16_t m;
- tmsize_t n;
- /* TODO: double-check: when subsamplingcorrect is set, no call to
- * TIFFErrorExt or TIFFWarningExt should be made in any other case, seek or
- * read errors should be passed through */
- do
- {
- if (sp->in_buffer_file_togo != 0)
- {
- if (sp->in_buffer_file_pos_log == 0)
- {
- TIFFSeekFile(sp->tif, sp->in_buffer_file_pos, SEEK_SET);
- sp->in_buffer_file_pos_log = 1;
- }
- m = OJPEG_BUFFER;
- if ((uint64_t)m > sp->in_buffer_file_togo)
- m = (uint16_t)sp->in_buffer_file_togo;
- n = TIFFReadFile(sp->tif, sp->in_buffer, (tmsize_t)m);
- if (n == 0)
- return (0);
- assert(n > 0);
- assert(n <= OJPEG_BUFFER);
- assert(n < 65536);
- assert((uint64_t)n <= sp->in_buffer_file_togo);
- m = (uint16_t)n;
- sp->in_buffer_togo = m;
- sp->in_buffer_cur = sp->in_buffer;
- sp->in_buffer_file_togo -= m;
- sp->in_buffer_file_pos += m;
- break;
- }
- sp->in_buffer_file_pos_log = 0;
- switch (sp->in_buffer_source)
- {
- case osibsNotSetYet:
- if (sp->jpeg_interchange_format != 0)
- {
- sp->in_buffer_file_pos = sp->jpeg_interchange_format;
- sp->in_buffer_file_togo =
- sp->jpeg_interchange_format_length;
- }
- sp->in_buffer_source = osibsJpegInterchangeFormat;
- break;
- case osibsJpegInterchangeFormat:
- sp->in_buffer_source = osibsStrile;
- break;
- case osibsStrile:
- if (sp->in_buffer_next_strile == sp->in_buffer_strile_count)
- sp->in_buffer_source = osibsEof;
- else
- {
- int err = 0;
- sp->in_buffer_file_pos = TIFFGetStrileOffsetWithErr(
- sp->tif, sp->in_buffer_next_strile, &err);
- if (err)
- return 0;
- if (sp->in_buffer_file_pos != 0)
- {
- uint64_t bytecount = TIFFGetStrileByteCountWithErr(
- sp->tif, sp->in_buffer_next_strile, &err);
- if (err)
- return 0;
- if (sp->in_buffer_file_pos >= sp->file_size)
- sp->in_buffer_file_pos = 0;
- else if (bytecount == 0)
- sp->in_buffer_file_togo =
- sp->file_size - sp->in_buffer_file_pos;
- else
- {
- sp->in_buffer_file_togo = bytecount;
- if (sp->in_buffer_file_togo == 0)
- sp->in_buffer_file_pos = 0;
- else if (sp->in_buffer_file_pos >
- UINT64_MAX - sp->in_buffer_file_togo ||
- sp->in_buffer_file_pos +
- sp->in_buffer_file_togo >
- sp->file_size)
- sp->in_buffer_file_togo =
- sp->file_size - sp->in_buffer_file_pos;
- }
- }
- sp->in_buffer_next_strile++;
- }
- break;
- default:
- return (0);
- }
- } while (1);
- return (1);
- }
- static int OJPEGReadByte(OJPEGState *sp, uint8_t *byte)
- {
- if (sp->in_buffer_togo == 0)
- {
- if (OJPEGReadBufferFill(sp) == 0)
- return (0);
- assert(sp->in_buffer_togo > 0);
- }
- *byte = *(sp->in_buffer_cur);
- sp->in_buffer_cur++;
- sp->in_buffer_togo--;
- return (1);
- }
- static int OJPEGReadBytePeek(OJPEGState *sp, uint8_t *byte)
- {
- if (sp->in_buffer_togo == 0)
- {
- if (OJPEGReadBufferFill(sp) == 0)
- return (0);
- assert(sp->in_buffer_togo > 0);
- }
- *byte = *(sp->in_buffer_cur);
- return (1);
- }
- static void OJPEGReadByteAdvance(OJPEGState *sp)
- {
- assert(sp->in_buffer_togo > 0);
- sp->in_buffer_cur++;
- sp->in_buffer_togo--;
- }
- static int OJPEGReadWord(OJPEGState *sp, uint16_t *word)
- {
- uint8_t m;
- if (OJPEGReadByte(sp, &m) == 0)
- return (0);
- *word = (m << 8);
- if (OJPEGReadByte(sp, &m) == 0)
- return (0);
- *word |= m;
- return (1);
- }
- static int OJPEGReadBlock(OJPEGState *sp, uint16_t len, void *mem)
- {
- uint16_t mlen;
- uint8_t *mmem;
- uint16_t n;
- assert(len > 0);
- mlen = len;
- mmem = mem;
- do
- {
- if (sp->in_buffer_togo == 0)
- {
- if (OJPEGReadBufferFill(sp) == 0)
- return (0);
- assert(sp->in_buffer_togo > 0);
- }
- n = mlen;
- if (n > sp->in_buffer_togo)
- n = sp->in_buffer_togo;
- _TIFFmemcpy(mmem, sp->in_buffer_cur, n);
- sp->in_buffer_cur += n;
- sp->in_buffer_togo -= n;
- mlen -= n;
- mmem += n;
- } while (mlen > 0);
- return (1);
- }
- static void OJPEGReadSkip(OJPEGState *sp, uint16_t len)
- {
- uint16_t m;
- uint16_t n;
- m = len;
- n = m;
- if (n > sp->in_buffer_togo)
- n = sp->in_buffer_togo;
- sp->in_buffer_cur += n;
- sp->in_buffer_togo -= n;
- m -= n;
- if (m > 0)
- {
- assert(sp->in_buffer_togo == 0);
- n = m;
- if ((uint64_t)n > sp->in_buffer_file_togo)
- n = (uint16_t)sp->in_buffer_file_togo;
- sp->in_buffer_file_pos += n;
- sp->in_buffer_file_togo -= n;
- sp->in_buffer_file_pos_log = 0;
- /* we don't skip past jpeginterchangeformat/strile block...
- * if that is asked from us, we're dealing with totally bazurk
- * data anyway, and we've not seen this happening on any
- * testfile, so we might as well likely cause some other
- * meaningless error to be passed at some later time
- */
- }
- }
- static int OJPEGWriteStream(TIFF *tif, void **mem, uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- *len = 0;
- do
- {
- assert(sp->out_state <= ososEoi);
- switch (sp->out_state)
- {
- case ososSoi:
- OJPEGWriteStreamSoi(tif, mem, len);
- break;
- case ososQTable0:
- OJPEGWriteStreamQTable(tif, 0, mem, len);
- break;
- case ososQTable1:
- OJPEGWriteStreamQTable(tif, 1, mem, len);
- break;
- case ososQTable2:
- OJPEGWriteStreamQTable(tif, 2, mem, len);
- break;
- case ososQTable3:
- OJPEGWriteStreamQTable(tif, 3, mem, len);
- break;
- case ososDcTable0:
- OJPEGWriteStreamDcTable(tif, 0, mem, len);
- break;
- case ososDcTable1:
- OJPEGWriteStreamDcTable(tif, 1, mem, len);
- break;
- case ososDcTable2:
- OJPEGWriteStreamDcTable(tif, 2, mem, len);
- break;
- case ososDcTable3:
- OJPEGWriteStreamDcTable(tif, 3, mem, len);
- break;
- case ososAcTable0:
- OJPEGWriteStreamAcTable(tif, 0, mem, len);
- break;
- case ososAcTable1:
- OJPEGWriteStreamAcTable(tif, 1, mem, len);
- break;
- case ososAcTable2:
- OJPEGWriteStreamAcTable(tif, 2, mem, len);
- break;
- case ososAcTable3:
- OJPEGWriteStreamAcTable(tif, 3, mem, len);
- break;
- case ososDri:
- OJPEGWriteStreamDri(tif, mem, len);
- break;
- case ososSof:
- OJPEGWriteStreamSof(tif, mem, len);
- break;
- case ososSos:
- OJPEGWriteStreamSos(tif, mem, len);
- break;
- case ososCompressed:
- if (OJPEGWriteStreamCompressed(tif, mem, len) == 0)
- return (0);
- break;
- case ososRst:
- OJPEGWriteStreamRst(tif, mem, len);
- break;
- case ososEoi:
- OJPEGWriteStreamEoi(tif, mem, len);
- break;
- }
- } while (*len == 0);
- return (1);
- }
- static void OJPEGWriteStreamSoi(TIFF *tif, void **mem, uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- assert(OJPEG_BUFFER >= 2);
- sp->out_buffer[0] = 255;
- sp->out_buffer[1] = JPEG_MARKER_SOI;
- *len = 2;
- *mem = (void *)sp->out_buffer;
- sp->out_state++;
- }
- static void OJPEGWriteStreamQTable(TIFF *tif, uint8_t table_index, void **mem,
- uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- if (sp->qtable[table_index] != 0)
- {
- *mem = (void *)(sp->qtable[table_index] + sizeof(uint32_t));
- *len = *((uint32_t *)sp->qtable[table_index]) - sizeof(uint32_t);
- }
- sp->out_state++;
- }
- static void OJPEGWriteStreamDcTable(TIFF *tif, uint8_t table_index, void **mem,
- uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- if (sp->dctable[table_index] != 0)
- {
- *mem = (void *)(sp->dctable[table_index] + sizeof(uint32_t));
- *len = *((uint32_t *)sp->dctable[table_index]) - sizeof(uint32_t);
- }
- sp->out_state++;
- }
- static void OJPEGWriteStreamAcTable(TIFF *tif, uint8_t table_index, void **mem,
- uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- if (sp->actable[table_index] != 0)
- {
- *mem = (void *)(sp->actable[table_index] + sizeof(uint32_t));
- *len = *((uint32_t *)sp->actable[table_index]) - sizeof(uint32_t);
- }
- sp->out_state++;
- }
- static void OJPEGWriteStreamDri(TIFF *tif, void **mem, uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- assert(OJPEG_BUFFER >= 6);
- if (sp->restart_interval != 0)
- {
- sp->out_buffer[0] = 255;
- sp->out_buffer[1] = JPEG_MARKER_DRI;
- sp->out_buffer[2] = 0;
- sp->out_buffer[3] = 4;
- sp->out_buffer[4] = (sp->restart_interval >> 8);
- sp->out_buffer[5] = (sp->restart_interval & 255);
- *len = 6;
- *mem = (void *)sp->out_buffer;
- }
- sp->out_state++;
- }
- static void OJPEGWriteStreamSof(TIFF *tif, void **mem, uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t m;
- assert(OJPEG_BUFFER >= 2 + 8 + sp->samples_per_pixel_per_plane * 3);
- assert(255 >= 8 + sp->samples_per_pixel_per_plane * 3);
- sp->out_buffer[0] = 255;
- sp->out_buffer[1] = sp->sof_marker_id;
- /* Lf */
- sp->out_buffer[2] = 0;
- sp->out_buffer[3] = 8 + sp->samples_per_pixel_per_plane * 3;
- /* P */
- sp->out_buffer[4] = 8;
- /* Y */
- sp->out_buffer[5] = (uint8_t)(sp->sof_y >> 8);
- sp->out_buffer[6] = (sp->sof_y & 255);
- /* X */
- sp->out_buffer[7] = (uint8_t)(sp->sof_x >> 8);
- sp->out_buffer[8] = (sp->sof_x & 255);
- /* Nf */
- sp->out_buffer[9] = sp->samples_per_pixel_per_plane;
- for (m = 0; m < sp->samples_per_pixel_per_plane; m++)
- {
- /* C */
- sp->out_buffer[10 + m * 3] = sp->sof_c[sp->plane_sample_offset + m];
- /* H and V */
- sp->out_buffer[10 + m * 3 + 1] =
- sp->sof_hv[sp->plane_sample_offset + m];
- /* Tq */
- sp->out_buffer[10 + m * 3 + 2] =
- sp->sof_tq[sp->plane_sample_offset + m];
- }
- *len = 10 + sp->samples_per_pixel_per_plane * 3;
- *mem = (void *)sp->out_buffer;
- sp->out_state++;
- }
- static void OJPEGWriteStreamSos(TIFF *tif, void **mem, uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- uint8_t m;
- assert(OJPEG_BUFFER >= 2 + 6 + sp->samples_per_pixel_per_plane * 2);
- assert(255 >= 6 + sp->samples_per_pixel_per_plane * 2);
- sp->out_buffer[0] = 255;
- sp->out_buffer[1] = JPEG_MARKER_SOS;
- /* Ls */
- sp->out_buffer[2] = 0;
- sp->out_buffer[3] = 6 + sp->samples_per_pixel_per_plane * 2;
- /* Ns */
- sp->out_buffer[4] = sp->samples_per_pixel_per_plane;
- for (m = 0; m < sp->samples_per_pixel_per_plane; m++)
- {
- /* Cs */
- sp->out_buffer[5 + m * 2] = sp->sos_cs[sp->plane_sample_offset + m];
- /* Td and Ta */
- sp->out_buffer[5 + m * 2 + 1] =
- sp->sos_tda[sp->plane_sample_offset + m];
- }
- /* Ss */
- sp->out_buffer[5 + sp->samples_per_pixel_per_plane * 2] = 0;
- /* Se */
- sp->out_buffer[5 + sp->samples_per_pixel_per_plane * 2 + 1] = 63;
- /* Ah and Al */
- sp->out_buffer[5 + sp->samples_per_pixel_per_plane * 2 + 2] = 0;
- *len = 8 + sp->samples_per_pixel_per_plane * 2;
- *mem = (void *)sp->out_buffer;
- sp->out_state++;
- }
- static int OJPEGWriteStreamCompressed(TIFF *tif, void **mem, uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- if (sp->in_buffer_togo == 0)
- {
- if (OJPEGReadBufferFill(sp) == 0)
- return (0);
- assert(sp->in_buffer_togo > 0);
- }
- *len = sp->in_buffer_togo;
- *mem = (void *)sp->in_buffer_cur;
- sp->in_buffer_togo = 0;
- if (sp->in_buffer_file_togo == 0)
- {
- switch (sp->in_buffer_source)
- {
- case osibsStrile:
- if (sp->in_buffer_next_strile < sp->in_buffer_strile_count)
- sp->out_state = ososRst;
- else
- sp->out_state = ososEoi;
- break;
- case osibsEof:
- sp->out_state = ososEoi;
- break;
- default:
- break;
- }
- }
- return (1);
- }
- static void OJPEGWriteStreamRst(TIFF *tif, void **mem, uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- assert(OJPEG_BUFFER >= 2);
- sp->out_buffer[0] = 255;
- sp->out_buffer[1] = JPEG_MARKER_RST0 + sp->restart_index;
- sp->restart_index++;
- if (sp->restart_index == 8)
- sp->restart_index = 0;
- *len = 2;
- *mem = (void *)sp->out_buffer;
- sp->out_state = ososCompressed;
- }
- static void OJPEGWriteStreamEoi(TIFF *tif, void **mem, uint32_t *len)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- assert(OJPEG_BUFFER >= 2);
- sp->out_buffer[0] = 255;
- sp->out_buffer[1] = JPEG_MARKER_EOI;
- *len = 2;
- *mem = (void *)sp->out_buffer;
- }
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- static int jpeg_create_decompress_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo)
- {
- if (SETJMP(sp->exit_jmpbuf))
- return 0;
- else
- {
- jpeg_create_decompress(cinfo);
- return 1;
- }
- }
- #endif
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- static int jpeg_read_header_encap(OJPEGState *sp, jpeg_decompress_struct *cinfo,
- uint8_t require_image)
- {
- if (SETJMP(sp->exit_jmpbuf))
- return 0;
- else
- {
- jpeg_read_header(cinfo, require_image);
- return 1;
- }
- }
- #endif
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- static int jpeg_start_decompress_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo)
- {
- if (SETJMP(sp->exit_jmpbuf))
- return 0;
- else
- {
- jpeg_start_decompress(cinfo);
- return 1;
- }
- }
- #endif
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- static int jpeg_read_scanlines_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo,
- void *scanlines, uint32_t max_lines)
- {
- if (SETJMP(sp->exit_jmpbuf))
- return 0;
- else
- {
- jpeg_read_scanlines(cinfo, scanlines, max_lines);
- return 1;
- }
- }
- #endif
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- static int jpeg_read_raw_data_encap(OJPEGState *sp,
- jpeg_decompress_struct *cinfo, void *data,
- uint32_t max_lines)
- {
- if (SETJMP(sp->exit_jmpbuf))
- return 0;
- else
- {
- jpeg_read_raw_data(cinfo, data, max_lines);
- return 1;
- }
- }
- #endif
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- static void jpeg_encap_unwind(TIFF *tif)
- {
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- LONGJMP(sp->exit_jmpbuf, 1);
- }
- #endif
- static void OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct *cinfo)
- {
- char buffer[JMSG_LENGTH_MAX];
- (*cinfo->err->format_message)(cinfo, buffer);
- TIFFWarningExtR(((TIFF *)(cinfo->client_data)), "LibJpeg", "%s", buffer);
- }
- static void OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct *cinfo)
- {
- char buffer[JMSG_LENGTH_MAX];
- (*cinfo->err->format_message)(cinfo, buffer);
- TIFFErrorExtR(((TIFF *)(cinfo->client_data)), "LibJpeg", "%s", buffer);
- jpeg_encap_unwind((TIFF *)(cinfo->client_data));
- }
- static void OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct *cinfo)
- {
- (void)cinfo;
- }
- static boolean
- OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct *cinfo)
- {
- TIFF *tif = (TIFF *)cinfo->client_data;
- OJPEGState *sp = (OJPEGState *)tif->tif_data;
- void *mem = 0;
- uint32_t len = 0U;
- if (OJPEGWriteStream(tif, &mem, &len) == 0)
- {
- TIFFErrorExtR(tif, "LibJpeg", "Premature end of JPEG data");
- jpeg_encap_unwind(tif);
- }
- sp->libjpeg_jpeg_source_mgr.bytes_in_buffer = len;
- sp->libjpeg_jpeg_source_mgr.next_input_byte = mem;
- return (1);
- }
- static void
- OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct *cinfo,
- long num_bytes)
- {
- TIFF *tif = (TIFF *)cinfo->client_data;
- (void)num_bytes;
- TIFFErrorExtR(tif, "LibJpeg", "Unexpected error");
- jpeg_encap_unwind(tif);
- }
- #ifdef _MSC_VER
- #pragma warning(push)
- #pragma warning(disable : 4702) /* unreachable code */
- #endif
- static boolean
- OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct *cinfo,
- int desired)
- {
- TIFF *tif = (TIFF *)cinfo->client_data;
- (void)desired;
- TIFFErrorExtR(tif, "LibJpeg", "Unexpected error");
- jpeg_encap_unwind(tif);
- return (0);
- }
- #ifdef _MSC_VER
- #pragma warning(pop)
- #endif
- static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct *cinfo)
- {
- (void)cinfo;
- }
- #endif
|