123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496 |
- /* $Id: tif_ojpeg.c,v 1.56 2012-05-24 03:15:18 fwarmerdam Exp $ */
- /* 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
- developement. 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. Allthough
- there is currently no define or other configuration mechanism to disable this behaviour,
- 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
- consistenly 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 dissadvantage 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
- * conviniently 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 accomodate 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. 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 conficting 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 "jpeglib.h"
- #include "jerror.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;
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- JMP_BUF exit_jmpbuf;
- #endif
- TIFFVGetMethod vgetparent;
- TIFFVSetMethod vsetparent;
- TIFFPrintMethod printdir;
- uint64 file_size;
- uint32 image_width;
- uint32 image_length;
- uint32 strile_width;
- uint32 strile_length;
- uint32 strile_length_total;
- uint8 samples_per_pixel;
- uint8 plane_sample_offset;
- uint8 samples_per_pixel_per_plane;
- uint64 jpeg_interchange_format;
- uint64 jpeg_interchange_format_length;
- uint8 jpeg_proc;
- uint8 subsamplingcorrect;
- uint8 subsamplingcorrect_done;
- uint8 subsampling_tag;
- uint8 subsampling_hor;
- uint8 subsampling_ver;
- uint8 subsampling_force_desubsampling_inside_decompression;
- uint8 qtable_offset_count;
- uint8 dctable_offset_count;
- uint8 actable_offset_count;
- uint64 qtable_offset[3];
- uint64 dctable_offset[3];
- uint64 actable_offset[3];
- uint8* qtable[4];
- uint8* dctable[4];
- uint8* actable[4];
- uint16 restart_interval;
- uint8 restart_index;
- uint8 sof_log;
- uint8 sof_marker_id;
- uint32 sof_x;
- uint32 sof_y;
- uint8 sof_c[3];
- uint8 sof_hv[3];
- uint8 sof_tq[3];
- uint8 sos_cs[3];
- uint8 sos_tda[3];
- struct {
- uint8 log;
- OJPEGStateInBufferSource in_buffer_source;
- uint32 in_buffer_next_strile;
- uint64 in_buffer_file_pos;
- uint64 in_buffer_file_togo;
- } sos_end[3];
- uint8 readheader_done;
- uint8 writeheader_done;
- uint16 write_cursample;
- uint32 write_curstrile;
- uint8 libjpeg_session_active;
- uint8 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 subsampling_convert_log;
- uint32 subsampling_convert_ylinelen;
- uint32 subsampling_convert_ylines;
- uint32 subsampling_convert_clinelen;
- uint32 subsampling_convert_clines;
- uint32 subsampling_convert_ybuflen;
- uint32 subsampling_convert_cbuflen;
- uint32 subsampling_convert_ycbcrbuflen;
- uint8* subsampling_convert_ycbcrbuf;
- uint8* subsampling_convert_ybuf;
- uint8* subsampling_convert_cbbuf;
- uint8* subsampling_convert_crbuf;
- uint32 subsampling_convert_ycbcrimagelen;
- uint8** subsampling_convert_ycbcrimage;
- uint32 subsampling_convert_clinelenout;
- uint32 subsampling_convert_state;
- uint32 bytes_per_line; /* if the codec outputs subsampled data, a 'line' in bytes_per_line */
- uint32 lines_per_strile; /* and lines_per_strile means subsampling_ver desubsampled rows */
- OJPEGStateInBufferSource in_buffer_source;
- uint32 in_buffer_next_strile;
- uint32 in_buffer_strile_count;
- uint64 in_buffer_file_pos;
- uint8 in_buffer_file_pos_log;
- uint64 in_buffer_file_togo;
- uint16 in_buffer_togo;
- uint8* in_buffer_cur;
- uint8 in_buffer[OJPEG_BUFFER];
- OJPEGStateOutState out_state;
- uint8 out_buffer[OJPEG_BUFFER];
- uint8* skip_buffer;
- } OJPEGState;
- static int OJPEGVGetField(TIFF* tif, uint32 tag, va_list ap);
- static int OJPEGVSetField(TIFF* tif, uint32 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 s);
- static int OJPEGPreDecodeSkipRaw(TIFF* tif);
- static int OJPEGPreDecodeSkipScanlines(TIFF* tif);
- static int OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s);
- static int OJPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc);
- static int OJPEGDecodeScanlines(TIFF* tif, uint8* buf, tmsize_t cc);
- static void OJPEGPostDecode(TIFF* tif, uint8* buf, tmsize_t cc);
- static int OJPEGSetupEncode(TIFF* tif);
- static int OJPEGPreEncode(TIFF* tif, uint16 s);
- static int OJPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 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 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 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* byte);
- static int OJPEGReadBytePeek(OJPEGState* sp, uint8* byte);
- static void OJPEGReadByteAdvance(OJPEGState* sp);
- static int OJPEGReadWord(OJPEGState* sp, uint16* word);
- static int OJPEGReadBlock(OJPEGState* sp, uint16 len, void* mem);
- static void OJPEGReadSkip(OJPEGState* sp, uint16 len);
- static int OJPEGWriteStream(TIFF* tif, void** mem, uint32* len);
- static void OJPEGWriteStreamSoi(TIFF* tif, void** mem, uint32* len);
- static void OJPEGWriteStreamQTable(TIFF* tif, uint8 table_index, void** mem, uint32* len);
- static void OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len);
- static void OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len);
- static void OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* len);
- static void OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len);
- static void OJPEGWriteStreamSos(TIFF* tif, void** mem, uint32* len);
- static int OJPEGWriteStreamCompressed(TIFF* tif, void** mem, uint32* len);
- static void OJPEGWriteStreamRst(TIFF* tif, void** mem, uint32* len);
- static void OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* 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 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 max_lines);
- extern int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 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 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 max_lines);
- static int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 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;
- assert(scheme==COMPRESSION_OJPEG);
- /*
- * Merge codec-specific tag information.
- */
- if (!_TIFFMergeFields(tif, ojpegFields, TIFFArrayCount(ojpegFields))) {
- TIFFErrorExt(tif->tif_clientdata, module,
- "Merging Old JPEG codec-specific tags failed");
- return 0;
- }
- /* state block */
- sp=_TIFFmalloc(sizeof(OJPEGState));
- if (sp==NULL)
- {
- TIFFErrorExt(tif->tif_clientdata,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*)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 tag, va_list ap)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- switch(tag)
- {
- case TIFFTAG_JPEGIFOFFSET:
- *va_arg(ap,uint64*)=(uint64)sp->jpeg_interchange_format;
- break;
- case TIFFTAG_JPEGIFBYTECOUNT:
- *va_arg(ap,uint64*)=(uint64)sp->jpeg_interchange_format_length;
- break;
- case TIFFTAG_YCBCRSUBSAMPLING:
- if (sp->subsamplingcorrect_done==0)
- OJPEGSubsamplingCorrect(tif);
- *va_arg(ap,uint16*)=(uint16)sp->subsampling_hor;
- *va_arg(ap,uint16*)=(uint16)sp->subsampling_ver;
- break;
- case TIFFTAG_JPEGQTABLES:
- *va_arg(ap,uint32*)=(uint32)sp->qtable_offset_count;
- *va_arg(ap,void**)=(void*)sp->qtable_offset;
- break;
- case TIFFTAG_JPEGDCTABLES:
- *va_arg(ap,uint32*)=(uint32)sp->dctable_offset_count;
- *va_arg(ap,void**)=(void*)sp->dctable_offset;
- break;
- case TIFFTAG_JPEGACTABLES:
- *va_arg(ap,uint32*)=(uint32)sp->actable_offset_count;
- *va_arg(ap,void**)=(void*)sp->actable_offset;
- break;
- case TIFFTAG_JPEGPROC:
- *va_arg(ap,uint16*)=(uint16)sp->jpeg_proc;
- break;
- case TIFFTAG_JPEGRESTARTINTERVAL:
- *va_arg(ap,uint16*)=sp->restart_interval;
- break;
- default:
- return (*sp->vgetparent)(tif,tag,ap);
- }
- return (1);
- }
- static int
- OJPEGVSetField(TIFF* tif, uint32 tag, va_list ap)
- {
- static const char module[]="OJPEGVSetField";
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- uint32 ma;
- uint64* mb;
- uint32 n;
- switch(tag)
- {
- case TIFFTAG_JPEGIFOFFSET:
- sp->jpeg_interchange_format=(uint64)va_arg(ap,uint64);
- break;
- case TIFFTAG_JPEGIFBYTECOUNT:
- sp->jpeg_interchange_format_length=(uint64)va_arg(ap,uint64);
- break;
- case TIFFTAG_YCBCRSUBSAMPLING:
- sp->subsampling_tag=1;
- sp->subsampling_hor=(uint8)va_arg(ap,uint16_vap);
- sp->subsampling_ver=(uint8)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)va_arg(ap,uint32);
- if (ma!=0)
- {
- if (ma>3)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"JpegQTables tag has incorrect count");
- return(0);
- }
- sp->qtable_offset_count=(uint8)ma;
- mb=(uint64*)va_arg(ap,uint64*);
- for (n=0; n<ma; n++)
- sp->qtable_offset[n]=mb[n];
- }
- break;
- case TIFFTAG_JPEGDCTABLES:
- ma=(uint32)va_arg(ap,uint32);
- if (ma!=0)
- {
- if (ma>3)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"JpegDcTables tag has incorrect count");
- return(0);
- }
- sp->dctable_offset_count=(uint8)ma;
- mb=(uint64*)va_arg(ap,uint64*);
- for (n=0; n<ma; n++)
- sp->dctable_offset[n]=mb[n];
- }
- break;
- case TIFFTAG_JPEGACTABLES:
- ma=(uint32)va_arg(ap,uint32);
- if (ma!=0)
- {
- if (ma>3)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"JpegAcTables tag has incorrect count");
- return(0);
- }
- sp->actable_offset_count=(uint8)ma;
- mb=(uint64*)va_arg(ap,uint64*);
- for (n=0; n<ma; n++)
- sp->actable_offset[n]=mb[n];
- }
- break;
- case TIFFTAG_JPEGPROC:
- sp->jpeg_proc=(uint8)va_arg(ap,uint16_vap);
- break;
- case TIFFTAG_JPEGRESTARTINTERVAL:
- sp->restart_interval=(uint16)va_arg(ap,uint16_vap);
- break;
- default:
- return (*sp->vsetparent)(tif,tag,ap);
- }
- TIFFSetFieldBit(tif,TIFFFieldWithTag(tif,tag)->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 m;
- (void)flags;
- assert(sp!=NULL);
- if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMAT))
- fprintf(fd," JpegInterchangeFormat: " TIFF_UINT64_FORMAT "\n",(TIFF_UINT64_T)sp->jpeg_interchange_format);
- if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH))
- fprintf(fd," JpegInterchangeFormatLength: " TIFF_UINT64_FORMAT "\n",(TIFF_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," " TIFF_UINT64_FORMAT,(TIFF_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," " TIFF_UINT64_FORMAT,(TIFF_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," " TIFF_UINT64_FORMAT,(TIFF_UINT64_T)sp->actable_offset[m]);
- fprintf(fd,"\n");
- }
- if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGPROC))
- fprintf(fd," JpegProc: %u\n",(unsigned int)sp->jpeg_proc);
- if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGRESTARTINTERVAL))
- fprintf(fd," JpegRestartInterval: %u\n",(unsigned int)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";
- TIFFWarningExt(tif->tif_clientdata,module,"Depreciated 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 s)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- uint32 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)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++;
- }
- return(1);
- }
- static int
- OJPEGPreDecodeSkipRaw(TIFF* tif)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- uint32 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;
- }
- 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 m;
- if (sp->skip_buffer==NULL)
- {
- sp->skip_buffer=_TIFFmalloc(sp->bytes_per_line);
- if (sp->skip_buffer==NULL)
- {
- TIFFErrorExt(tif->tif_clientdata,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* buf, tmsize_t cc, uint16 s)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- (void)s;
- 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* buf, tmsize_t cc)
- {
- static const char module[]="OJPEGDecodeRaw";
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- uint8* m;
- tmsize_t n;
- uint8* oy;
- uint8* ocb;
- uint8* ocr;
- uint8* p;
- uint32 q;
- uint8* r;
- uint8 sx,sy;
- if (cc%sp->bytes_per_line!=0)
- {
- TIFFErrorExt(tif->tif_clientdata,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)
- 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* buf, tmsize_t cc)
- {
- static const char module[]="OJPEGDecodeScanlines";
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- uint8* m;
- tmsize_t n;
- if (cc%sp->bytes_per_line!=0)
- {
- TIFFErrorExt(tif->tif_clientdata,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* buf, tmsize_t cc)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- (void)buf;
- (void)cc;
- 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";
- TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
- return(0);
- }
- static int
- OJPEGPreEncode(TIFF* tif, uint16 s)
- {
- static const char module[]="OJPEGPreEncode";
- (void)s;
- TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
- return(0);
- }
- static int
- OJPEGEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
- {
- static const char module[]="OJPEGEncode";
- (void)buf;
- (void)cc;
- (void)s;
- TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
- return(0);
- }
- static int
- OJPEGPostEncode(TIFF* tif)
- {
- static const char module[]="OJPEGPostEncode";
- TIFFErrorExt(tif->tif_clientdata,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)
- _TIFFfree(sp->qtable[0]);
- if (sp->qtable[1]!=0)
- _TIFFfree(sp->qtable[1]);
- if (sp->qtable[2]!=0)
- _TIFFfree(sp->qtable[2]);
- if (sp->qtable[3]!=0)
- _TIFFfree(sp->qtable[3]);
- if (sp->dctable[0]!=0)
- _TIFFfree(sp->dctable[0]);
- if (sp->dctable[1]!=0)
- _TIFFfree(sp->dctable[1]);
- if (sp->dctable[2]!=0)
- _TIFFfree(sp->dctable[2]);
- if (sp->dctable[3]!=0)
- _TIFFfree(sp->dctable[3]);
- if (sp->actable[0]!=0)
- _TIFFfree(sp->actable[0]);
- if (sp->actable[1]!=0)
- _TIFFfree(sp->actable[1]);
- if (sp->actable[2]!=0)
- _TIFFfree(sp->actable[2]);
- if (sp->actable[3]!=0)
- _TIFFfree(sp->actable[3]);
- if (sp->libjpeg_session_active!=0)
- OJPEGLibjpegSessionAbort(tif);
- if (sp->subsampling_convert_ycbcrbuf!=0)
- _TIFFfree(sp->subsampling_convert_ycbcrbuf);
- if (sp->subsampling_convert_ycbcrimage!=0)
- _TIFFfree(sp->subsampling_convert_ycbcrimage);
- if (sp->skip_buffer!=0)
- _TIFFfree(sp->skip_buffer);
- _TIFFfree(sp);
- tif->tif_data=NULL;
- _TIFFSetDefaultCompressionState(tif);
- }
- }
- static void
- OJPEGSubsamplingCorrect(TIFF* tif)
- {
- static const char module[]="OJPEGSubsamplingCorrect";
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- uint8 mh;
- uint8 mv;
- _TIFFFillStriles( tif );
-
- 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)
- TIFFWarningExt(tif->tif_clientdata,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)
- TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data [%d,%d] does not match default values [2,2]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver);
- else
- TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data [%d,%d] does not match subsampling tag values [%d,%d]; 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)
- TIFFWarningExt(tif->tif_clientdata,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
- TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data does not match subsampling tag values [%d,%d] (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)
- TIFFWarningExt(tif->tif_clientdata,module,"Subsampling values [%d,%d] 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;
- 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)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"SamplesPerPixel %d 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->strile_length%(sp->subsampling_ver*8)!=0)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length");
- return(0);
- }
- sp->restart_interval=((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 s)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- uint8 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=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** m;
- uint32 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);
- 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;
- sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(sp->subsampling_convert_ycbcrbuflen);
- if (sp->subsampling_convert_ycbcrbuf==0)
- {
- TIFFErrorExt(tif->tif_clientdata,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=_TIFFmalloc(sp->subsampling_convert_ycbcrimagelen*sizeof(uint8*));
- if (sp->subsampling_convert_ycbcrimage==0)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
- return(0);
- }
- m=sp->subsampling_convert_ycbcrimage;
- *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3);
- *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines);
- *m++=(uint8*)(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-1)/sp->subsampling_hor);
- sp->subsampling_convert_state=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-1)/sp->subsampling_ver);
- 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);
- 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 m;
- uint16 n;
- uint8 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+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)
- TIFFErrorExt(tif->tif_clientdata,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:
- TIFFErrorExt(tif->tif_clientdata,module,"Unknown marker type %d 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 easilly cause trouble in some cases... but no such cases have occured sofar */
- static const char module[]="OJPEGReadHeaderInfoSecStreamDri";
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- uint16 m;
- if (OJPEGReadWord(sp,&m)==0)
- return(0);
- if (m!=4)
- {
- TIFFErrorExt(tif->tif_clientdata,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 m;
- uint32 na;
- uint8* nb;
- uint8 o;
- if (OJPEGReadWord(sp,&m)==0)
- return(0);
- if (m<=2)
- {
- if (sp->subsamplingcorrect==0)
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data");
- return(0);
- }
- if (sp->subsamplingcorrect!=0)
- OJPEGReadSkip(sp,m-2);
- else
- {
- m-=2;
- do
- {
- if (m<65)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data");
- return(0);
- }
- na=sizeof(uint32)+69;
- nb=_TIFFmalloc(na);
- if (nb==0)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
- return(0);
- }
- *(uint32*)nb=na;
- nb[sizeof(uint32)]=255;
- nb[sizeof(uint32)+1]=JPEG_MARKER_DQT;
- nb[sizeof(uint32)+2]=0;
- nb[sizeof(uint32)+3]=67;
- if (OJPEGReadBlock(sp,65,&nb[sizeof(uint32)+4])==0) {
- _TIFFfree(nb);
- return(0);
- }
- o=nb[sizeof(uint32)+4]&15;
- if (3<o)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data");
- _TIFFfree(nb);
- return(0);
- }
- if (sp->qtable[o]!=0)
- _TIFFfree(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 m;
- uint32 na;
- uint8* nb;
- uint8 o;
- if (OJPEGReadWord(sp,&m)==0)
- return(0);
- if (m<=2)
- {
- if (sp->subsamplingcorrect==0)
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
- return(0);
- }
- if (sp->subsamplingcorrect!=0)
- {
- OJPEGReadSkip(sp,m-2);
- }
- else
- {
- na=sizeof(uint32)+2+m;
- nb=_TIFFmalloc(na);
- if (nb==0)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
- return(0);
- }
- *(uint32*)nb=na;
- nb[sizeof(uint32)]=255;
- nb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
- nb[sizeof(uint32)+2]=(m>>8);
- nb[sizeof(uint32)+3]=(m&255);
- if (OJPEGReadBlock(sp,m-2,&nb[sizeof(uint32)+4])==0)
- return(0);
- o=nb[sizeof(uint32)+4];
- if ((o&240)==0)
- {
- if (3<o)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
- return(0);
- }
- if (sp->dctable[o]!=0)
- _TIFFfree(sp->dctable[o]);
- sp->dctable[o]=nb;
- }
- else
- {
- if ((o&240)!=16)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
- return(0);
- }
- o&=15;
- if (3<o)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
- return(0);
- }
- if (sp->actable[o]!=0)
- _TIFFfree(sp->actable[o]);
- sp->actable[o]=nb;
- }
- }
- return(1);
- }
- static int
- OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 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 m;
- uint16 n;
- uint8 o;
- uint16 p;
- uint16 q;
- if (sp->sof_log!=0)
- {
- TIFFErrorExt(tif->tif_clientdata,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)
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data");
- return(0);
- }
- m-=8;
- if (m%3!=0)
- {
- if (sp->subsamplingcorrect==0)
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data");
- return(0);
- }
- n=m/3;
- if (sp->subsamplingcorrect==0)
- {
- if (n!=sp->samples_per_pixel)
- {
- TIFFErrorExt(tif->tif_clientdata,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)
- TIFFErrorExt(tif->tif_clientdata,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)p<sp->image_length) && ((uint32)p<sp->strile_length_total))
- {
- TIFFErrorExt(tif->tif_clientdata,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)p<sp->image_width) && ((uint32)p<sp->strile_width))
- {
- TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected width");
- return(0);
- }
- if ((uint32)p>sp->strile_width)
- {
- TIFFErrorExt(tif->tif_clientdata,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)
- TIFFErrorExt(tif->tif_clientdata,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))
- {
- TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values");
- return(0);
- }
- }
- else
- {
- if (o!=17)
- {
- TIFFErrorExt(tif->tif_clientdata,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 m;
- uint8 n;
- uint8 o;
- assert(sp->subsamplingcorrect==0);
- if (sp->sof_log==0)
- {
- TIFFErrorExt(tif->tif_clientdata,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)
- {
- TIFFErrorExt(tif->tif_clientdata,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)
- {
- TIFFErrorExt(tif->tif_clientdata,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 m;
- uint8 n;
- uint32 oa;
- uint8* ob;
- uint32 p;
- if (sp->qtable_offset[0]==0)
- {
- TIFFErrorExt(tif->tif_clientdata,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])
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegQTables tag value");
- return(0);
- }
- }
- oa=sizeof(uint32)+69;
- ob=_TIFFmalloc(oa);
- if (ob==0)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
- return(0);
- }
- *(uint32*)ob=oa;
- ob[sizeof(uint32)]=255;
- ob[sizeof(uint32)+1]=JPEG_MARKER_DQT;
- ob[sizeof(uint32)+2]=0;
- ob[sizeof(uint32)+3]=67;
- ob[sizeof(uint32)+4]=m;
- TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET);
- p=TIFFReadFile(tif,&ob[sizeof(uint32)+5],64);
- if (p!=64)
- return(0);
- 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 m;
- uint8 n;
- uint8 o[16];
- uint32 p;
- uint32 q;
- uint32 ra;
- uint8* rb;
- if (sp->dctable_offset[0]==0)
- {
- TIFFErrorExt(tif->tif_clientdata,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])
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegDcTables tag value");
- return(0);
- }
- }
- TIFFSeekFile(tif,sp->dctable_offset[m],SEEK_SET);
- p=TIFFReadFile(tif,o,16);
- if (p!=16)
- return(0);
- q=0;
- for (n=0; n<16; n++)
- q+=o[n];
- ra=sizeof(uint32)+21+q;
- rb=_TIFFmalloc(ra);
- if (rb==0)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
- return(0);
- }
- *(uint32*)rb=ra;
- rb[sizeof(uint32)]=255;
- rb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
- rb[sizeof(uint32)+2]=((19+q)>>8);
- rb[sizeof(uint32)+3]=((19+q)&255);
- rb[sizeof(uint32)+4]=m;
- for (n=0; n<16; n++)
- rb[sizeof(uint32)+5+n]=o[n];
- p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
- if (p!=q)
- return(0);
- 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 m;
- uint8 n;
- uint8 o[16];
- uint32 p;
- uint32 q;
- uint32 ra;
- uint8* rb;
- if (sp->actable_offset[0]==0)
- {
- TIFFErrorExt(tif->tif_clientdata,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])
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegAcTables tag value");
- return(0);
- }
- }
- TIFFSeekFile(tif,sp->actable_offset[m],SEEK_SET);
- p=TIFFReadFile(tif,o,16);
- if (p!=16)
- return(0);
- q=0;
- for (n=0; n<16; n++)
- q+=o[n];
- ra=sizeof(uint32)+21+q;
- rb=_TIFFmalloc(ra);
- if (rb==0)
- {
- TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
- return(0);
- }
- *(uint32*)rb=ra;
- rb[sizeof(uint32)]=255;
- rb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
- rb[sizeof(uint32)+2]=((19+q)>>8);
- rb[sizeof(uint32)+3]=((19+q)&255);
- rb[sizeof(uint32)+4]=(16|m);
- for (n=0; n<16; n++)
- rb[sizeof(uint32)+5+n]=o[n];
- p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
- if (p!=q)
- return(0);
- 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 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)m>sp->in_buffer_file_togo)
- m=(uint16)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)n<=sp->in_buffer_file_togo);
- m=(uint16)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;
- case osibsStrile:
- if (!_TIFFFillStriles( sp->tif )
- || sp->tif->tif_dir.td_stripoffset == NULL
- || sp->tif->tif_dir.td_stripbytecount == NULL)
- return 0;
- if (sp->in_buffer_next_strile==sp->in_buffer_strile_count)
- sp->in_buffer_source=osibsEof;
- else
- {
- sp->in_buffer_file_pos=sp->tif->tif_dir.td_stripoffset[sp->in_buffer_next_strile];
- if (sp->in_buffer_file_pos!=0)
- {
- if (sp->in_buffer_file_pos>=sp->file_size)
- sp->in_buffer_file_pos=0;
- else if (sp->tif->tif_dir.td_stripbytecount==NULL)
- sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
- else
- {
- if (sp->tif->tif_dir.td_stripbytecount == 0) {
- TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip byte counts are missing");
- return(0);
- }
- sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile];
- if (sp->in_buffer_file_togo==0)
- sp->in_buffer_file_pos=0;
- else if (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* 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* 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* word)
- {
- uint8 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 len, void* mem)
- {
- uint16 mlen;
- uint8* mmem;
- uint16 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 len)
- {
- uint16 m;
- uint16 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)n>sp->in_buffer_file_togo)
- n=(uint16)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* 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* 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 table_index, void** mem, uint32* len)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- if (sp->qtable[table_index]!=0)
- {
- *mem=(void*)(sp->qtable[table_index]+sizeof(uint32));
- *len=*((uint32*)sp->qtable[table_index])-sizeof(uint32);
- }
- sp->out_state++;
- }
- static void
- OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- if (sp->dctable[table_index]!=0)
- {
- *mem=(void*)(sp->dctable[table_index]+sizeof(uint32));
- *len=*((uint32*)sp->dctable[table_index])-sizeof(uint32);
- }
- sp->out_state++;
- }
- static void
- OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- if (sp->actable[table_index]!=0)
- {
- *mem=(void*)(sp->actable[table_index]+sizeof(uint32));
- *len=*((uint32*)sp->actable[table_index])-sizeof(uint32);
- }
- sp->out_state++;
- }
- static void
- OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* 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* len)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- uint8 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]=(sp->sof_y>>8);
- sp->out_buffer[6]=(sp->sof_y&255);
- /* X */
- sp->out_buffer[7]=(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* len)
- {
- OJPEGState* sp=(OJPEGState*)tif->tif_data;
- uint8 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* 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* 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* 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)
- {
- return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_create_decompress(cinfo),1));
- }
- #endif
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- static int
- jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image)
- {
- return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_header(cinfo,require_image),1));
- }
- #endif
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- static int
- jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo)
- {
- return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_start_decompress(cinfo),1));
- }
- #endif
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- static int
- jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines)
- {
- return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_scanlines(cinfo,scanlines,max_lines),1));
- }
- #endif
- #ifndef LIBJPEG_ENCAP_EXTERNAL
- static int
- jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines)
- {
- return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_raw_data(cinfo,data,max_lines),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);
- TIFFWarningExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg","%s",buffer);
- }
- static void
- OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct* cinfo)
- {
- char buffer[JMSG_LENGTH_MAX];
- (*cinfo->err->format_message)(cinfo,buffer);
- TIFFErrorExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"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 len=0U;
- if (OJPEGWriteStream(tif,&mem,&len)==0)
- {
- TIFFErrorExt(tif->tif_clientdata,"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;
- TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error");
- jpeg_encap_unwind(tif);
- }
- static boolean
- OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired)
- {
- TIFF* tif=(TIFF*)cinfo->client_data;
- (void)desired;
- TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error");
- jpeg_encap_unwind(tif);
- return(0);
- }
- static void
- OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo)
- {
- (void)cinfo;
- }
- #endif
- /*
- * Local Variables:
- * mode: c
- * c-basic-offset: 8
- * fill-column: 78
- * End:
- */
|