1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815 |
- /* 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,
- TIFF_SETGET_UNDEFINED, FIELD_OJPEG_JPEGINTERCHANGEFORMAT, TRUE, FALSE,
- "JpegInterchangeFormat", NULL},
- {TIFFTAG_JPEGIFBYTECOUNT, 1, 1, TIFF_LONG8, 0, TIFF_SETGET_UINT64,
- TIFF_SETGET_UNDEFINED, FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH, TRUE,
- FALSE, "JpegInterchangeFormatLength", NULL},
- {TIFFTAG_JPEGQTABLES, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_LONG8, 0,
- TIFF_SETGET_C32_UINT64, TIFF_SETGET_UNDEFINED, FIELD_OJPEG_JPEGQTABLES,
- FALSE, TRUE, "JpegQTables", NULL},
- {TIFFTAG_JPEGDCTABLES, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_LONG8, 0,
- TIFF_SETGET_C32_UINT64, TIFF_SETGET_UNDEFINED, FIELD_OJPEG_JPEGDCTABLES,
- FALSE, TRUE, "JpegDcTables", NULL},
- {TIFFTAG_JPEGACTABLES, TIFF_VARIABLE2, TIFF_VARIABLE2, TIFF_LONG8, 0,
- TIFF_SETGET_C32_UINT64, TIFF_SETGET_UNDEFINED, FIELD_OJPEG_JPEGACTABLES,
- FALSE, TRUE, "JpegAcTables", NULL},
- {TIFFTAG_JPEGPROC, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_OJPEG_JPEGPROC, FALSE, FALSE, "JpegProc",
- NULL},
- {TIFFTAG_JPEGRESTARTINTERVAL, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
- TIFF_SETGET_UNDEFINED, FIELD_OJPEG_JPEGRESTARTINTERVAL, FALSE, FALSE,
- "JpegRestartInterval", NULL},
- };
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- #include <setjmp.h>
- #endif
- /* We undefine FAR to avoid conflict with JPEG definition */
- #ifdef FAR
- #undef FAR
- #endif
- /*
- Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
- not defined. Unfortunately, the MinGW and Borland compilers include
- a typedef for INT32, which causes a conflict. MSVC does not include
- a conflicting typedef given the headers which are included.
- */
- #if defined(__BORLANDC__) || defined(__MINGW32__)
- #define XMD_H 1
- #endif
- /* Define "boolean" as unsigned char, not int, per Windows custom. */
- #if defined(__WIN32__) && !defined(__MINGW32__)
- #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
- typedef unsigned char boolean;
- #endif
- #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
- #endif
- #include "jerror.h"
- #include "jpeglib.h"
- typedef struct jpeg_error_mgr jpeg_error_mgr;
- typedef struct jpeg_common_struct jpeg_common_struct;
- typedef struct jpeg_decompress_struct jpeg_decompress_struct;
- typedef struct jpeg_source_mgr jpeg_source_mgr;
- 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);
- }
- 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)
- {
- TIFFErrorExtR(tif, module,
- "Cannot decode: decoder not correctly initialized");
- return 0;
- }
- if (sp->libjpeg_session_active == 0)
- {
- /* 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)
- {
- return 0;
- }
- if (sp->libjpeg_jpeg_query_style == 0)
- {
- if (OJPEGDecodeRaw(tif, buf, cc) == 0)
- return (0);
- }
- else
- {
- if (OJPEGDecodeScanlines(tif, buf, cc) == 0)
- 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
|