12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620 |
- /*
- * Copyright (c) 1988-1997 Sam Leffler
- * Copyright (c) 1991-1997 Silicon Graphics, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that (i) the above copyright notices and this permission notice appear in
- * all copies of the software and related documentation, and (ii) the names of
- * Sam Leffler and Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Sam Leffler and Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS 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.
- */
- /*
- * TIFF Library.
- *
- * Directory Write Support Routines.
- */
- #include "tiffiop.h"
- #include <float.h> /*--: for Rational2Double */
- #include <math.h> /*--: for Rational2Double */
- #ifdef HAVE_IEEEFP
- #define TIFFCvtNativeToIEEEFloat(tif, n, fp)
- #define TIFFCvtNativeToIEEEDouble(tif, n, dp)
- #else
- extern void TIFFCvtNativeToIEEEFloat(TIFF *tif, uint32_t n, float *fp);
- extern void TIFFCvtNativeToIEEEDouble(TIFF *tif, uint32_t n, double *dp);
- #endif
- static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
- uint64_t *pdiroff);
- static int TIFFWriteDirectoryTagSampleformatArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- double *value);
- static int TIFFWriteDirectoryTagAscii(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, char *value);
- static int TIFFWriteDirectoryTagUndefinedArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint8_t *value);
- static int TIFFWriteDirectoryTagByteArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint8_t *value);
- static int TIFFWriteDirectoryTagSbyteArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, int8_t *value);
- static int TIFFWriteDirectoryTagShort(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint16_t value);
- static int TIFFWriteDirectoryTagShortArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint16_t *value);
- static int TIFFWriteDirectoryTagShortPerSample(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint16_t value);
- static int TIFFWriteDirectoryTagSshortArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, int16_t *value);
- static int TIFFWriteDirectoryTagLong(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t value);
- static int TIFFWriteDirectoryTagLongArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint32_t *value);
- static int TIFFWriteDirectoryTagSlongArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, int32_t *value);
- static int TIFFWriteDirectoryTagLong8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint64_t *value);
- static int TIFFWriteDirectoryTagSlong8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, int64_t *value);
- static int TIFFWriteDirectoryTagRational(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- double value);
- static int TIFFWriteDirectoryTagRationalArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, float *value);
- static int TIFFWriteDirectoryTagSrationalArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, float *value);
- static int TIFFWriteDirectoryTagFloatArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, float *value);
- static int TIFFWriteDirectoryTagDoubleArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, double *value);
- static int TIFFWriteDirectoryTagIfdArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint32_t *value);
- static int TIFFWriteDirectoryTagShortLong(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t value);
- static int TIFFWriteDirectoryTagLongLong8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint64_t *value);
- static int TIFFWriteDirectoryTagIfdIfd8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint64_t *value);
- static int TIFFWriteDirectoryTagColormap(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir);
- static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir);
- static int TIFFWriteDirectoryTagSubifd(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir);
- static int TIFFWriteDirectoryTagCheckedAscii(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, char *value);
- static int TIFFWriteDirectoryTagCheckedUndefinedArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag,
- uint32_t count,
- uint8_t *value);
- static int TIFFWriteDirectoryTagCheckedByteArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- uint8_t *value);
- static int TIFFWriteDirectoryTagCheckedSbyteArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- int8_t *value);
- static int TIFFWriteDirectoryTagCheckedShort(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint16_t value);
- static int TIFFWriteDirectoryTagCheckedShortArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- uint16_t *value);
- static int TIFFWriteDirectoryTagCheckedSshortArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- int16_t *value);
- static int TIFFWriteDirectoryTagCheckedLong(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t value);
- static int TIFFWriteDirectoryTagCheckedLongArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- uint32_t *value);
- static int TIFFWriteDirectoryTagCheckedSlongArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- int32_t *value);
- static int TIFFWriteDirectoryTagCheckedLong8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- uint64_t *value);
- static int TIFFWriteDirectoryTagCheckedSlong8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- int64_t *value);
- static int TIFFWriteDirectoryTagCheckedRational(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- double value);
- static int TIFFWriteDirectoryTagCheckedRationalArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag,
- uint32_t count,
- float *value);
- static int TIFFWriteDirectoryTagCheckedSrationalArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag,
- uint32_t count,
- float *value);
- /*--: Rational2Double: New functions to support true double-precision for custom
- * rational tag types. */
- static int TIFFWriteDirectoryTagRationalDoubleArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag,
- uint32_t count,
- double *value);
- static int TIFFWriteDirectoryTagSrationalDoubleArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag,
- uint32_t count,
- double *value);
- static int
- TIFFWriteDirectoryTagCheckedRationalDoubleArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, double *value);
- static int TIFFWriteDirectoryTagCheckedSrationalDoubleArray(
- TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count,
- double *value);
- static void DoubleToRational(double value, uint32_t *num, uint32_t *denom);
- static void DoubleToSrational(double value, int32_t *num, int32_t *denom);
- static int TIFFWriteDirectoryTagCheckedFloatArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- float *value);
- static int TIFFWriteDirectoryTagCheckedDoubleArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- double *value);
- static int TIFFWriteDirectoryTagCheckedIfdArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count,
- uint32_t *value);
- static int TIFFWriteDirectoryTagCheckedIfd8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- uint64_t *value);
- static int TIFFWriteDirectoryTagData(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint16_t datatype, uint32_t count,
- uint32_t datalength, void *data);
- static int TIFFLinkDirectory(TIFF *);
- /*
- * Write the contents of the current directory
- * to the specified file. This routine doesn't
- * handle overwriting a directory with auxiliary
- * storage that's been changed.
- */
- int TIFFWriteDirectory(TIFF *tif)
- {
- return TIFFWriteDirectorySec(tif, TRUE, TRUE, NULL);
- }
- /*
- * This is an advanced writing function that must be used in a particular
- * sequence, and generally together with TIFFForceStrileArrayWriting(),
- * to make its intended effect. Its aim is to modify the location
- * where the [Strip/Tile][Offsets/ByteCounts] arrays are located in the file.
- * More precisely, when TIFFWriteCheck() will be called, the tag entries for
- * those arrays will be written with type = count = offset = 0 as a temporary
- * value.
- *
- * Its effect is only valid for the current directory, and before
- * TIFFWriteDirectory() is first called, and will be reset when
- * changing directory.
- *
- * The typical sequence of calls is:
- * TIFFOpen()
- * [ TIFFCreateDirectory(tif) ]
- * Set fields with calls to TIFFSetField(tif, ...)
- * TIFFDeferStrileArrayWriting(tif)
- * TIFFWriteCheck(tif, ...)
- * TIFFWriteDirectory(tif)
- * ... potentially create other directories and come back to the above directory
- * TIFFForceStrileArrayWriting(tif): emit the arrays at the end of file
- *
- * Returns 1 in case of success, 0 otherwise.
- */
- int TIFFDeferStrileArrayWriting(TIFF *tif)
- {
- static const char module[] = "TIFFDeferStrileArrayWriting";
- if (tif->tif_mode == O_RDONLY)
- {
- TIFFErrorExtR(tif, tif->tif_name, "File opened in read-only mode");
- return 0;
- }
- if (tif->tif_diroff != 0)
- {
- TIFFErrorExtR(tif, module, "Directory has already been written");
- return 0;
- }
- tif->tif_dir.td_deferstrilearraywriting = TRUE;
- return 1;
- }
- /*
- * Similar to TIFFWriteDirectory(), writes the directory out
- * but leaves all data structures in memory so that it can be
- * written again. This will make a partially written TIFF file
- * readable before it is successfully completed/closed.
- */
- int TIFFCheckpointDirectory(TIFF *tif)
- {
- int rc;
- /* Setup the strips arrays, if they haven't already been. */
- if (tif->tif_dir.td_stripoffset_p == NULL)
- (void)TIFFSetupStrips(tif);
- rc = TIFFWriteDirectorySec(tif, TRUE, FALSE, NULL);
- (void)TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END));
- return rc;
- }
- int TIFFWriteCustomDirectory(TIFF *tif, uint64_t *pdiroff)
- {
- return TIFFWriteDirectorySec(tif, FALSE, FALSE, pdiroff);
- }
- /*
- * Similar to TIFFWriteDirectory(), but if the directory has already
- * been written once, it is relocated to the end of the file, in case it
- * has changed in size. Note that this will result in the loss of the
- * previously used directory space.
- */
- int TIFFRewriteDirectory(TIFF *tif)
- {
- static const char module[] = "TIFFRewriteDirectory";
- /* We don't need to do anything special if it hasn't been written. */
- if (tif->tif_diroff == 0)
- return TIFFWriteDirectory(tif);
- /*
- * Find and zero the pointer to this directory, so that TIFFLinkDirectory
- * will cause it to be added after this directories current pre-link.
- */
- uint64_t torewritediroff = tif->tif_diroff;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- if (tif->tif_header.classic.tiff_diroff == tif->tif_diroff)
- {
- tif->tif_header.classic.tiff_diroff = 0;
- tif->tif_diroff = 0;
- TIFFSeekFile(tif, 4, SEEK_SET);
- if (!WriteOK(tif, &(tif->tif_header.classic.tiff_diroff), 4))
- {
- TIFFErrorExtR(tif, tif->tif_name, "Error updating TIFF header");
- return (0);
- }
- }
- else if (tif->tif_diroff > 0xFFFFFFFFU)
- {
- TIFFErrorExtR(tif, module,
- "tif->tif_diroff exceeds 32 bit range allowed for "
- "Classic TIFF");
- return (0);
- }
- else
- {
- uint32_t nextdir;
- nextdir = tif->tif_header.classic.tiff_diroff;
- while (1)
- {
- uint16_t dircount;
- uint32_t nextnextdir;
- if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount, 2))
- {
- TIFFErrorExtR(tif, module,
- "Error fetching directory count");
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(&dircount);
- (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET);
- if (!ReadOK(tif, &nextnextdir, 4))
- {
- TIFFErrorExtR(tif, module, "Error fetching directory link");
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&nextnextdir);
- if (nextnextdir == tif->tif_diroff)
- {
- uint32_t m;
- m = 0;
- (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12,
- SEEK_SET);
- if (!WriteOK(tif, &m, 4))
- {
- TIFFErrorExtR(tif, module,
- "Error writing directory link");
- return (0);
- }
- tif->tif_diroff = 0;
- /* Force a full-traversal to reach the zeroed pointer */
- tif->tif_lastdiroff = 0;
- break;
- }
- nextdir = nextnextdir;
- }
- }
- /* Remove skipped offset from IFD loop directory list. */
- _TIFFRemoveEntryFromDirectoryListByOffset(tif, torewritediroff);
- }
- else
- {
- if (tif->tif_header.big.tiff_diroff == tif->tif_diroff)
- {
- tif->tif_header.big.tiff_diroff = 0;
- tif->tif_diroff = 0;
- TIFFSeekFile(tif, 8, SEEK_SET);
- if (!WriteOK(tif, &(tif->tif_header.big.tiff_diroff), 8))
- {
- TIFFErrorExtR(tif, tif->tif_name, "Error updating TIFF header");
- return (0);
- }
- }
- else
- {
- uint64_t nextdir;
- nextdir = tif->tif_header.big.tiff_diroff;
- while (1)
- {
- uint64_t dircount64;
- uint16_t dircount;
- uint64_t nextnextdir;
- if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8))
- {
- TIFFErrorExtR(tif, module,
- "Error fetching directory count");
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&dircount64);
- if (dircount64 > 0xFFFF)
- {
- TIFFErrorExtR(tif, module,
- "Sanity check on tag count failed, likely "
- "corrupt TIFF");
- return (0);
- }
- dircount = (uint16_t)dircount64;
- (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET);
- if (!ReadOK(tif, &nextnextdir, 8))
- {
- TIFFErrorExtR(tif, module, "Error fetching directory link");
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&nextnextdir);
- if (nextnextdir == tif->tif_diroff)
- {
- uint64_t m;
- m = 0;
- (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20,
- SEEK_SET);
- if (!WriteOK(tif, &m, 8))
- {
- TIFFErrorExtR(tif, module,
- "Error writing directory link");
- return (0);
- }
- tif->tif_diroff = 0;
- /* Force a full-traversal to reach the zeroed pointer */
- tif->tif_lastdiroff = 0;
- break;
- }
- nextdir = nextnextdir;
- }
- }
- /* Remove skipped offset from IFD loop directory list. */
- _TIFFRemoveEntryFromDirectoryListByOffset(tif, torewritediroff);
- }
- /*
- * Now use TIFFWriteDirectory() normally.
- */
- return TIFFWriteDirectory(tif);
- }
- static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone,
- uint64_t *pdiroff)
- {
- static const char module[] = "TIFFWriteDirectorySec";
- uint32_t ndir;
- TIFFDirEntry *dir;
- uint32_t dirsize;
- void *dirmem;
- uint32_t m;
- if (tif->tif_mode == O_RDONLY)
- return (1);
- _TIFFFillStriles(tif);
- /*
- * Clear write state so that subsequent images with
- * different characteristics get the right buffers
- * setup for them.
- */
- if (imagedone)
- {
- if (tif->tif_flags & TIFF_POSTENCODE)
- {
- tif->tif_flags &= ~TIFF_POSTENCODE;
- if (!(*tif->tif_postencode)(tif))
- {
- TIFFErrorExtR(tif, module,
- "Error post-encoding before directory write");
- return (0);
- }
- }
- (*tif->tif_close)(tif); /* shutdown encoder */
- /*
- * Flush any data that might have been written
- * by the compression close+cleanup routines. But
- * be careful not to write stuff if we didn't add data
- * in the previous steps as the "rawcc" data may well be
- * a previously read tile/strip in mixed read/write mode.
- */
- if (tif->tif_rawcc > 0 && (tif->tif_flags & TIFF_BEENWRITING) != 0)
- {
- if (!TIFFFlushData1(tif))
- {
- TIFFErrorExtR(tif, module,
- "Error flushing data before directory write");
- return (0);
- }
- }
- if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata)
- {
- _TIFFfreeExt(tif, tif->tif_rawdata);
- tif->tif_rawdata = NULL;
- tif->tif_rawcc = 0;
- tif->tif_rawdatasize = 0;
- tif->tif_rawdataoff = 0;
- tif->tif_rawdataloaded = 0;
- }
- tif->tif_flags &= ~(TIFF_BEENWRITING | TIFF_BUFFERSETUP);
- }
- if (TIFFFieldSet(tif, FIELD_COMPRESSION) &&
- (tif->tif_dir.td_compression == COMPRESSION_DEFLATE))
- {
- TIFFWarningExtR(tif, module,
- "Creating TIFF with legacy Deflate codec identifier, "
- "COMPRESSION_ADOBE_DEFLATE is more widely supported");
- }
- dir = NULL;
- dirmem = NULL;
- dirsize = 0;
- while (1)
- {
- ndir = 0;
- if (isimage)
- {
- if (TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS))
- {
- if (!TIFFWriteDirectoryTagShortLong(tif, &ndir, dir,
- TIFFTAG_IMAGEWIDTH,
- tif->tif_dir.td_imagewidth))
- goto bad;
- if (!TIFFWriteDirectoryTagShortLong(
- tif, &ndir, dir, TIFFTAG_IMAGELENGTH,
- tif->tif_dir.td_imagelength))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_TILEDIMENSIONS))
- {
- if (!TIFFWriteDirectoryTagShortLong(tif, &ndir, dir,
- TIFFTAG_TILEWIDTH,
- tif->tif_dir.td_tilewidth))
- goto bad;
- if (!TIFFWriteDirectoryTagShortLong(tif, &ndir, dir,
- TIFFTAG_TILELENGTH,
- tif->tif_dir.td_tilelength))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_RESOLUTION))
- {
- if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
- TIFFTAG_XRESOLUTION,
- tif->tif_dir.td_xresolution))
- goto bad;
- if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
- TIFFTAG_YRESOLUTION,
- tif->tif_dir.td_yresolution))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_POSITION))
- {
- if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
- TIFFTAG_XPOSITION,
- tif->tif_dir.td_xposition))
- goto bad;
- if (!TIFFWriteDirectoryTagRational(tif, &ndir, dir,
- TIFFTAG_YPOSITION,
- tif->tif_dir.td_yposition))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_SUBFILETYPE))
- {
- if (!TIFFWriteDirectoryTagLong(tif, &ndir, dir,
- TIFFTAG_SUBFILETYPE,
- tif->tif_dir.td_subfiletype))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_BITSPERSAMPLE))
- {
- if (!TIFFWriteDirectoryTagShortPerSample(
- tif, &ndir, dir, TIFFTAG_BITSPERSAMPLE,
- tif->tif_dir.td_bitspersample))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_COMPRESSION))
- {
- if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
- TIFFTAG_COMPRESSION,
- tif->tif_dir.td_compression))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_PHOTOMETRIC))
- {
- if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
- TIFFTAG_PHOTOMETRIC,
- tif->tif_dir.td_photometric))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_THRESHHOLDING))
- {
- if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
- TIFFTAG_THRESHHOLDING,
- tif->tif_dir.td_threshholding))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_FILLORDER))
- {
- if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
- TIFFTAG_FILLORDER,
- tif->tif_dir.td_fillorder))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_ORIENTATION))
- {
- if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
- TIFFTAG_ORIENTATION,
- tif->tif_dir.td_orientation))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_SAMPLESPERPIXEL))
- {
- if (!TIFFWriteDirectoryTagShort(
- tif, &ndir, dir, TIFFTAG_SAMPLESPERPIXEL,
- tif->tif_dir.td_samplesperpixel))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
- {
- if (!TIFFWriteDirectoryTagShortLong(
- tif, &ndir, dir, TIFFTAG_ROWSPERSTRIP,
- tif->tif_dir.td_rowsperstrip))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_MINSAMPLEVALUE))
- {
- if (!TIFFWriteDirectoryTagShortPerSample(
- tif, &ndir, dir, TIFFTAG_MINSAMPLEVALUE,
- tif->tif_dir.td_minsamplevalue))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE))
- {
- if (!TIFFWriteDirectoryTagShortPerSample(
- tif, &ndir, dir, TIFFTAG_MAXSAMPLEVALUE,
- tif->tif_dir.td_maxsamplevalue))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_PLANARCONFIG))
- {
- if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
- TIFFTAG_PLANARCONFIG,
- tif->tif_dir.td_planarconfig))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_RESOLUTIONUNIT))
- {
- if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
- TIFFTAG_RESOLUTIONUNIT,
- tif->tif_dir.td_resolutionunit))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_PAGENUMBER))
- {
- if (!TIFFWriteDirectoryTagShortArray(
- tif, &ndir, dir, TIFFTAG_PAGENUMBER, 2,
- &tif->tif_dir.td_pagenumber[0]))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS))
- {
- if (!isTiled(tif))
- {
- if (!TIFFWriteDirectoryTagLongLong8Array(
- tif, &ndir, dir, TIFFTAG_STRIPBYTECOUNTS,
- tif->tif_dir.td_nstrips,
- tif->tif_dir.td_stripbytecount_p))
- goto bad;
- }
- else
- {
- if (!TIFFWriteDirectoryTagLongLong8Array(
- tif, &ndir, dir, TIFFTAG_TILEBYTECOUNTS,
- tif->tif_dir.td_nstrips,
- tif->tif_dir.td_stripbytecount_p))
- goto bad;
- }
- }
- if (TIFFFieldSet(tif, FIELD_STRIPOFFSETS))
- {
- if (!isTiled(tif))
- {
- /* td_stripoffset_p might be NULL in an odd OJPEG case. See
- * tif_dirread.c around line 3634.
- * XXX: OJPEG hack.
- * If a) compression is OJPEG, b) it's not a tiled TIFF,
- * and c) the number of strips is 1,
- * then we tolerate the absence of stripoffsets tag,
- * because, presumably, all required data is in the
- * JpegInterchangeFormat stream.
- * We can get here when using tiffset on such a file.
- * See http://bugzilla.maptools.org/show_bug.cgi?id=2500
- */
- if (tif->tif_dir.td_stripoffset_p != NULL &&
- !TIFFWriteDirectoryTagLongLong8Array(
- tif, &ndir, dir, TIFFTAG_STRIPOFFSETS,
- tif->tif_dir.td_nstrips,
- tif->tif_dir.td_stripoffset_p))
- goto bad;
- }
- else
- {
- if (!TIFFWriteDirectoryTagLongLong8Array(
- tif, &ndir, dir, TIFFTAG_TILEOFFSETS,
- tif->tif_dir.td_nstrips,
- tif->tif_dir.td_stripoffset_p))
- goto bad;
- }
- }
- if (TIFFFieldSet(tif, FIELD_COLORMAP))
- {
- if (!TIFFWriteDirectoryTagColormap(tif, &ndir, dir))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_EXTRASAMPLES))
- {
- if (tif->tif_dir.td_extrasamples)
- {
- uint16_t na;
- uint16_t *nb;
- TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &na, &nb);
- if (!TIFFWriteDirectoryTagShortArray(
- tif, &ndir, dir, TIFFTAG_EXTRASAMPLES, na, nb))
- goto bad;
- }
- }
- if (TIFFFieldSet(tif, FIELD_SAMPLEFORMAT))
- {
- if (!TIFFWriteDirectoryTagShortPerSample(
- tif, &ndir, dir, TIFFTAG_SAMPLEFORMAT,
- tif->tif_dir.td_sampleformat))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_SMINSAMPLEVALUE))
- {
- if (!TIFFWriteDirectoryTagSampleformatArray(
- tif, &ndir, dir, TIFFTAG_SMINSAMPLEVALUE,
- tif->tif_dir.td_samplesperpixel,
- tif->tif_dir.td_sminsamplevalue))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_SMAXSAMPLEVALUE))
- {
- if (!TIFFWriteDirectoryTagSampleformatArray(
- tif, &ndir, dir, TIFFTAG_SMAXSAMPLEVALUE,
- tif->tif_dir.td_samplesperpixel,
- tif->tif_dir.td_smaxsamplevalue))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_IMAGEDEPTH))
- {
- if (!TIFFWriteDirectoryTagLong(tif, &ndir, dir,
- TIFFTAG_IMAGEDEPTH,
- tif->tif_dir.td_imagedepth))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_TILEDEPTH))
- {
- if (!TIFFWriteDirectoryTagLong(tif, &ndir, dir,
- TIFFTAG_TILEDEPTH,
- tif->tif_dir.td_tiledepth))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_HALFTONEHINTS))
- {
- if (!TIFFWriteDirectoryTagShortArray(
- tif, &ndir, dir, TIFFTAG_HALFTONEHINTS, 2,
- &tif->tif_dir.td_halftonehints[0]))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_YCBCRSUBSAMPLING))
- {
- if (!TIFFWriteDirectoryTagShortArray(
- tif, &ndir, dir, TIFFTAG_YCBCRSUBSAMPLING, 2,
- &tif->tif_dir.td_ycbcrsubsampling[0]))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_YCBCRPOSITIONING))
- {
- if (!TIFFWriteDirectoryTagShort(
- tif, &ndir, dir, TIFFTAG_YCBCRPOSITIONING,
- tif->tif_dir.td_ycbcrpositioning))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_REFBLACKWHITE))
- {
- if (!TIFFWriteDirectoryTagRationalArray(
- tif, &ndir, dir, TIFFTAG_REFERENCEBLACKWHITE, 6,
- tif->tif_dir.td_refblackwhite))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_TRANSFERFUNCTION))
- {
- if (!TIFFWriteDirectoryTagTransferfunction(tif, &ndir, dir))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_INKNAMES))
- {
- if (!TIFFWriteDirectoryTagAscii(
- tif, &ndir, dir, TIFFTAG_INKNAMES,
- tif->tif_dir.td_inknameslen, tif->tif_dir.td_inknames))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_NUMBEROFINKS))
- {
- if (!TIFFWriteDirectoryTagShort(tif, &ndir, dir,
- TIFFTAG_NUMBEROFINKS,
- tif->tif_dir.td_numberofinks))
- goto bad;
- }
- if (TIFFFieldSet(tif, FIELD_SUBIFD))
- {
- if (!TIFFWriteDirectoryTagSubifd(tif, &ndir, dir))
- goto bad;
- }
- {
- uint32_t n;
- for (n = 0; n < tif->tif_nfields; n++)
- {
- const TIFFField *o;
- o = tif->tif_fields[n];
- if ((o->field_bit >= FIELD_CODEC) &&
- (TIFFFieldSet(tif, o->field_bit)))
- {
- switch (o->get_field_type)
- {
- case TIFF_SETGET_ASCII:
- {
- uint32_t pa;
- char *pb;
- assert(o->field_type == TIFF_ASCII);
- assert(o->field_readcount == TIFF_VARIABLE);
- assert(o->field_passcount == 0);
- TIFFGetField(tif, o->field_tag, &pb);
- pa = (uint32_t)(strlen(pb));
- if (!TIFFWriteDirectoryTagAscii(
- tif, &ndir, dir, (uint16_t)o->field_tag,
- pa, pb))
- goto bad;
- }
- break;
- case TIFF_SETGET_UINT16:
- {
- uint16_t p;
- assert(o->field_type == TIFF_SHORT);
- assert(o->field_readcount == 1);
- assert(o->field_passcount == 0);
- TIFFGetField(tif, o->field_tag, &p);
- if (!TIFFWriteDirectoryTagShort(
- tif, &ndir, dir, (uint16_t)o->field_tag,
- p))
- goto bad;
- }
- break;
- case TIFF_SETGET_UINT32:
- {
- uint32_t p;
- assert(o->field_type == TIFF_LONG);
- assert(o->field_readcount == 1);
- assert(o->field_passcount == 0);
- TIFFGetField(tif, o->field_tag, &p);
- if (!TIFFWriteDirectoryTagLong(
- tif, &ndir, dir, (uint16_t)o->field_tag,
- p))
- goto bad;
- }
- break;
- case TIFF_SETGET_C32_UINT8:
- {
- uint32_t pa;
- void *pb;
- assert(o->field_type == TIFF_UNDEFINED);
- assert(o->field_readcount == TIFF_VARIABLE2);
- assert(o->field_passcount == 1);
- TIFFGetField(tif, o->field_tag, &pa, &pb);
- if (!TIFFWriteDirectoryTagUndefinedArray(
- tif, &ndir, dir, (uint16_t)o->field_tag,
- pa, pb))
- goto bad;
- }
- break;
- default:
- TIFFErrorExtR(
- tif, module,
- "Cannot write tag %" PRIu32 " (%s)",
- TIFFFieldTag(o),
- o->field_name ? o->field_name : "unknown");
- goto bad;
- }
- }
- }
- }
- }
- for (m = 0; m < (uint32_t)(tif->tif_dir.td_customValueCount); m++)
- {
- uint16_t tag =
- (uint16_t)tif->tif_dir.td_customValues[m].info->field_tag;
- uint32_t count = tif->tif_dir.td_customValues[m].count;
- switch (tif->tif_dir.td_customValues[m].info->field_type)
- {
- case TIFF_ASCII:
- if (!TIFFWriteDirectoryTagAscii(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_UNDEFINED:
- if (!TIFFWriteDirectoryTagUndefinedArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_BYTE:
- if (!TIFFWriteDirectoryTagByteArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_SBYTE:
- if (!TIFFWriteDirectoryTagSbyteArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_SHORT:
- if (!TIFFWriteDirectoryTagShortArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_SSHORT:
- if (!TIFFWriteDirectoryTagSshortArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_LONG:
- if (!TIFFWriteDirectoryTagLongArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_SLONG:
- if (!TIFFWriteDirectoryTagSlongArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_LONG8:
- if (!TIFFWriteDirectoryTagLong8Array(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_SLONG8:
- if (!TIFFWriteDirectoryTagSlong8Array(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_RATIONAL:
- {
- /*-- Rational2Double: For Rationals evaluate
- * "set_field_type" to determine internal storage size. */
- int tv_size;
- tv_size = TIFFFieldSetGetSize(
- tif->tif_dir.td_customValues[m].info);
- if (tv_size == 8)
- {
- if (!TIFFWriteDirectoryTagRationalDoubleArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- }
- else
- {
- /*-- default should be tv_size == 4 */
- if (!TIFFWriteDirectoryTagRationalArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- /*-- ToDo: After Testing, this should be removed and
- * tv_size==4 should be set as default. */
- if (tv_size != 4)
- {
- TIFFErrorExtR(tif,
- "TIFFLib: _TIFFWriteDirectorySec()",
- "Rational2Double: .set_field_type is "
- "not 4 but %d",
- tv_size);
- }
- }
- }
- break;
- case TIFF_SRATIONAL:
- {
- /*-- Rational2Double: For Rationals evaluate
- * "set_field_type" to determine internal storage size. */
- int tv_size;
- tv_size = TIFFFieldSetGetSize(
- tif->tif_dir.td_customValues[m].info);
- if (tv_size == 8)
- {
- if (!TIFFWriteDirectoryTagSrationalDoubleArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- }
- else
- {
- /*-- default should be tv_size == 4 */
- if (!TIFFWriteDirectoryTagSrationalArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- /*-- ToDo: After Testing, this should be removed and
- * tv_size==4 should be set as default. */
- if (tv_size != 4)
- {
- TIFFErrorExtR(tif,
- "TIFFLib: _TIFFWriteDirectorySec()",
- "Rational2Double: .set_field_type is "
- "not 4 but %d",
- tv_size);
- }
- }
- }
- break;
- case TIFF_FLOAT:
- if (!TIFFWriteDirectoryTagFloatArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_DOUBLE:
- if (!TIFFWriteDirectoryTagDoubleArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_IFD:
- if (!TIFFWriteDirectoryTagIfdArray(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- case TIFF_IFD8:
- if (!TIFFWriteDirectoryTagIfdIfd8Array(
- tif, &ndir, dir, tag, count,
- tif->tif_dir.td_customValues[m].value))
- goto bad;
- break;
- default:
- assert(0); /* we should never get here */
- break;
- }
- }
- if (dir != NULL)
- break;
- dir = _TIFFmallocExt(tif, ndir * sizeof(TIFFDirEntry));
- if (dir == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- goto bad;
- }
- if (isimage)
- {
- if ((tif->tif_diroff == 0) && (!TIFFLinkDirectory(tif)))
- goto bad;
- }
- else
- tif->tif_diroff =
- (TIFFSeekFile(tif, 0, SEEK_END) + 1) & (~((toff_t)1));
- if (pdiroff != NULL)
- *pdiroff = tif->tif_diroff;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- dirsize = 2 + ndir * 12 + 4;
- else
- dirsize = 8 + ndir * 20 + 8;
- tif->tif_dataoff = tif->tif_diroff + dirsize;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- tif->tif_dataoff = (uint32_t)tif->tif_dataoff;
- if ((tif->tif_dataoff < tif->tif_diroff) ||
- (tif->tif_dataoff < (uint64_t)dirsize))
- {
- TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
- goto bad;
- }
- if (tif->tif_dataoff & 1)
- tif->tif_dataoff++;
- if (isimage)
- {
- if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER)
- tif->tif_curdir = 0;
- else
- tif->tif_curdir++;
- }
- }
- if (isimage)
- {
- if (TIFFFieldSet(tif, FIELD_SUBIFD) && (tif->tif_subifdoff == 0))
- {
- uint32_t na;
- TIFFDirEntry *nb;
- for (na = 0, nb = dir;; na++, nb++)
- {
- if (na == ndir)
- {
- TIFFErrorExtR(tif, module, "Cannot find SubIFD tag");
- goto bad;
- }
- if (nb->tdir_tag == TIFFTAG_SUBIFD)
- break;
- }
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- tif->tif_subifdoff = tif->tif_diroff + 2 + na * 12 + 8;
- else
- tif->tif_subifdoff = tif->tif_diroff + 8 + na * 20 + 12;
- }
- }
- dirmem = _TIFFmallocExt(tif, dirsize);
- if (dirmem == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- goto bad;
- }
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- uint8_t *n;
- uint32_t nTmp;
- TIFFDirEntry *o;
- n = dirmem;
- *(uint16_t *)n = (uint16_t)ndir;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)n);
- n += 2;
- o = dir;
- for (m = 0; m < ndir; m++)
- {
- *(uint16_t *)n = o->tdir_tag;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)n);
- n += 2;
- *(uint16_t *)n = o->tdir_type;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)n);
- n += 2;
- nTmp = (uint32_t)o->tdir_count;
- _TIFFmemcpy(n, &nTmp, 4);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)n);
- n += 4;
- /* This is correct. The data has been */
- /* swabbed previously in TIFFWriteDirectoryTagData */
- _TIFFmemcpy(n, &o->tdir_offset, 4);
- n += 4;
- o++;
- }
- nTmp = (uint32_t)tif->tif_nextdiroff;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&nTmp);
- _TIFFmemcpy(n, &nTmp, 4);
- }
- else
- {
- uint8_t *n;
- TIFFDirEntry *o;
- n = dirmem;
- *(uint64_t *)n = ndir;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)n);
- n += 8;
- o = dir;
- for (m = 0; m < ndir; m++)
- {
- *(uint16_t *)n = o->tdir_tag;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)n);
- n += 2;
- *(uint16_t *)n = o->tdir_type;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)n);
- n += 2;
- _TIFFmemcpy(n, &o->tdir_count, 8);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)n);
- n += 8;
- _TIFFmemcpy(n, &o->tdir_offset, 8);
- n += 8;
- o++;
- }
- _TIFFmemcpy(n, &tif->tif_nextdiroff, 8);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)n);
- }
- _TIFFfreeExt(tif, dir);
- dir = NULL;
- if (!SeekOK(tif, tif->tif_diroff))
- {
- TIFFErrorExtR(tif, module, "IO error writing directory");
- goto bad;
- }
- if (!WriteOK(tif, dirmem, (tmsize_t)dirsize))
- {
- TIFFErrorExtR(tif, module, "IO error writing directory");
- goto bad;
- }
- _TIFFfreeExt(tif, dirmem);
- if (imagedone)
- {
- TIFFFreeDirectory(tif);
- tif->tif_flags &= ~TIFF_DIRTYDIRECT;
- tif->tif_flags &= ~TIFF_DIRTYSTRIP;
- (*tif->tif_cleanup)(tif);
- /*
- * Reset directory-related state for subsequent
- * directories.
- */
- TIFFCreateDirectory(tif);
- }
- return (1);
- bad:
- if (dir != NULL)
- _TIFFfreeExt(tif, dir);
- if (dirmem != NULL)
- _TIFFfreeExt(tif, dirmem);
- return (0);
- }
- static int8_t TIFFClampDoubleToInt8(double val)
- {
- if (val > 127)
- return 127;
- if (val < -128 || val != val)
- return -128;
- return (int8_t)val;
- }
- static int16_t TIFFClampDoubleToInt16(double val)
- {
- if (val > 32767)
- return 32767;
- if (val < -32768 || val != val)
- return -32768;
- return (int16_t)val;
- }
- static int32_t TIFFClampDoubleToInt32(double val)
- {
- if (val > 0x7FFFFFFF)
- return 0x7FFFFFFF;
- if (val < -0x7FFFFFFF - 1 || val != val)
- return -0x7FFFFFFF - 1;
- return (int32_t)val;
- }
- static uint8_t TIFFClampDoubleToUInt8(double val)
- {
- if (val < 0)
- return 0;
- if (val > 255 || val != val)
- return 255;
- return (uint8_t)val;
- }
- static uint16_t TIFFClampDoubleToUInt16(double val)
- {
- if (val < 0)
- return 0;
- if (val > 65535 || val != val)
- return 65535;
- return (uint16_t)val;
- }
- static uint32_t TIFFClampDoubleToUInt32(double val)
- {
- if (val < 0)
- return 0;
- if (val > 0xFFFFFFFFU || val != val)
- return 0xFFFFFFFFU;
- return (uint32_t)val;
- }
- static int TIFFWriteDirectoryTagSampleformatArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- double *value)
- {
- static const char module[] = "TIFFWriteDirectoryTagSampleformatArray";
- void *conv;
- uint32_t i;
- int ok;
- conv = _TIFFmallocExt(tif, count * sizeof(double));
- if (conv == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- switch (tif->tif_dir.td_sampleformat)
- {
- case SAMPLEFORMAT_IEEEFP:
- if (tif->tif_dir.td_bitspersample <= 32)
- {
- for (i = 0; i < count; ++i)
- ((float *)conv)[i] = _TIFFClampDoubleToFloat(value[i]);
- ok = TIFFWriteDirectoryTagFloatArray(tif, ndir, dir, tag, count,
- (float *)conv);
- }
- else
- {
- ok = TIFFWriteDirectoryTagDoubleArray(tif, ndir, dir, tag,
- count, value);
- }
- break;
- case SAMPLEFORMAT_INT:
- if (tif->tif_dir.td_bitspersample <= 8)
- {
- for (i = 0; i < count; ++i)
- ((int8_t *)conv)[i] = TIFFClampDoubleToInt8(value[i]);
- ok = TIFFWriteDirectoryTagSbyteArray(tif, ndir, dir, tag, count,
- (int8_t *)conv);
- }
- else if (tif->tif_dir.td_bitspersample <= 16)
- {
- for (i = 0; i < count; ++i)
- ((int16_t *)conv)[i] = TIFFClampDoubleToInt16(value[i]);
- ok = TIFFWriteDirectoryTagSshortArray(tif, ndir, dir, tag,
- count, (int16_t *)conv);
- }
- else
- {
- for (i = 0; i < count; ++i)
- ((int32_t *)conv)[i] = TIFFClampDoubleToInt32(value[i]);
- ok = TIFFWriteDirectoryTagSlongArray(tif, ndir, dir, tag, count,
- (int32_t *)conv);
- }
- break;
- case SAMPLEFORMAT_UINT:
- if (tif->tif_dir.td_bitspersample <= 8)
- {
- for (i = 0; i < count; ++i)
- ((uint8_t *)conv)[i] = TIFFClampDoubleToUInt8(value[i]);
- ok = TIFFWriteDirectoryTagByteArray(tif, ndir, dir, tag, count,
- (uint8_t *)conv);
- }
- else if (tif->tif_dir.td_bitspersample <= 16)
- {
- for (i = 0; i < count; ++i)
- ((uint16_t *)conv)[i] = TIFFClampDoubleToUInt16(value[i]);
- ok = TIFFWriteDirectoryTagShortArray(tif, ndir, dir, tag, count,
- (uint16_t *)conv);
- }
- else
- {
- for (i = 0; i < count; ++i)
- ((uint32_t *)conv)[i] = TIFFClampDoubleToUInt32(value[i]);
- ok = TIFFWriteDirectoryTagLongArray(tif, ndir, dir, tag, count,
- (uint32_t *)conv);
- }
- break;
- default:
- ok = 0;
- }
- _TIFFfreeExt(tif, conv);
- return (ok);
- }
- static int TIFFWriteDirectoryTagAscii(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, char *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (
- TIFFWriteDirectoryTagCheckedAscii(tif, ndir, dir, tag, count, value));
- }
- static int TIFFWriteDirectoryTagUndefinedArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint8_t *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedUndefinedArray(tif, ndir, dir, tag,
- count, value));
- }
- static int TIFFWriteDirectoryTagByteArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint8_t *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedByteArray(tif, ndir, dir, tag, count,
- value));
- }
- static int TIFFWriteDirectoryTagSbyteArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, int8_t *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedSbyteArray(tif, ndir, dir, tag, count,
- value));
- }
- static int TIFFWriteDirectoryTagShort(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint16_t value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedShort(tif, ndir, dir, tag, value));
- }
- static int TIFFWriteDirectoryTagShortArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint16_t *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, tag, count,
- value));
- }
- static int TIFFWriteDirectoryTagShortPerSample(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint16_t value)
- {
- static const char module[] = "TIFFWriteDirectoryTagShortPerSample";
- uint16_t *m;
- uint16_t *na;
- uint16_t nb;
- int o;
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- m = _TIFFmallocExt(tif, tif->tif_dir.td_samplesperpixel * sizeof(uint16_t));
- if (m == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- for (na = m, nb = 0; nb < tif->tif_dir.td_samplesperpixel; na++, nb++)
- *na = value;
- o = TIFFWriteDirectoryTagCheckedShortArray(
- tif, ndir, dir, tag, tif->tif_dir.td_samplesperpixel, m);
- _TIFFfreeExt(tif, m);
- return (o);
- }
- static int TIFFWriteDirectoryTagSshortArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, int16_t *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedSshortArray(tif, ndir, dir, tag, count,
- value));
- }
- static int TIFFWriteDirectoryTagLong(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedLong(tif, ndir, dir, tag, value));
- }
- static int TIFFWriteDirectoryTagLongArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint32_t *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedLongArray(tif, ndir, dir, tag, count,
- value));
- }
- static int TIFFWriteDirectoryTagSlongArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, int32_t *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedSlongArray(tif, ndir, dir, tag, count,
- value));
- }
- /************************************************************************/
- /* TIFFWriteDirectoryTagLong8Array() */
- /* */
- /* Write either Long8 or Long array depending on file type. */
- /************************************************************************/
- static int TIFFWriteDirectoryTagLong8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint64_t *value)
- {
- static const char module[] = "TIFFWriteDirectoryTagLong8Array";
- uint64_t *ma;
- uint32_t mb;
- uint32_t *p;
- uint32_t *q;
- int o;
- /* is this just a counting pass? */
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- /* We always write Long8 for BigTIFF, no checking needed. */
- if (tif->tif_flags & TIFF_BIGTIFF)
- return (TIFFWriteDirectoryTagCheckedLong8Array(tif, ndir, dir, tag,
- count, value));
- /*
- ** For classic tiff we want to verify everything is in range for long
- ** and convert to long format.
- */
- p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
- if (p == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- for (q = p, ma = value, mb = 0; mb < count; ma++, mb++, q++)
- {
- if (*ma > 0xFFFFFFFF)
- {
- TIFFErrorExtR(tif, module,
- "Attempt to write unsigned long value %" PRIu64
- " larger than 0xFFFFFFFF for tag %d in Classic TIFF "
- "file. TIFF file writing aborted",
- *ma, tag);
- _TIFFfreeExt(tif, p);
- return (0);
- }
- *q = (uint32_t)(*ma);
- }
- o = TIFFWriteDirectoryTagCheckedLongArray(tif, ndir, dir, tag, count, p);
- _TIFFfreeExt(tif, p);
- return (o);
- }
- /************************************************************************/
- /* TIFFWriteDirectoryTagSlong8Array() */
- /* */
- /* Write either SLong8 or SLong array depending on file type. */
- /************************************************************************/
- static int TIFFWriteDirectoryTagSlong8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, int64_t *value)
- {
- static const char module[] = "TIFFWriteDirectoryTagSlong8Array";
- int64_t *ma;
- uint32_t mb;
- int32_t *p;
- int32_t *q;
- int o;
- /* is this just a counting pass? */
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- /* We always write SLong8 for BigTIFF, no checking needed. */
- if (tif->tif_flags & TIFF_BIGTIFF)
- return (TIFFWriteDirectoryTagCheckedSlong8Array(tif, ndir, dir, tag,
- count, value));
- /*
- ** For classic tiff we want to verify everything is in range for signed-long
- ** and convert to signed-long format.
- */
- p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
- if (p == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- for (q = p, ma = value, mb = 0; mb < count; ma++, mb++, q++)
- {
- if (*ma > (2147483647))
- {
- TIFFErrorExtR(tif, module,
- "Attempt to write signed long value %" PRIi64
- " larger than 0x7FFFFFFF (2147483647) for tag %d in "
- "Classic TIFF file. TIFF writing to file aborted",
- *ma, tag);
- _TIFFfreeExt(tif, p);
- return (0);
- }
- else if (*ma < (-2147483647 - 1))
- {
- TIFFErrorExtR(tif, module,
- "Attempt to write signed long value %" PRIi64
- " smaller than 0x80000000 (-2147483648) for tag %d "
- "in Classic TIFF file. TIFF writing to file aborted",
- *ma, tag);
- _TIFFfreeExt(tif, p);
- return (0);
- }
- *q = (int32_t)(*ma);
- }
- o = TIFFWriteDirectoryTagCheckedSlongArray(tif, ndir, dir, tag, count, p);
- _TIFFfreeExt(tif, p);
- return (o);
- }
- static int TIFFWriteDirectoryTagRational(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- double value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedRational(tif, ndir, dir, tag, value));
- }
- static int TIFFWriteDirectoryTagRationalArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, float *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedRationalArray(tif, ndir, dir, tag,
- count, value));
- }
- static int TIFFWriteDirectoryTagSrationalArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, float *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedSrationalArray(tif, ndir, dir, tag,
- count, value));
- }
- /*-- Rational2Double: additional write functions */
- static int TIFFWriteDirectoryTagRationalDoubleArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag,
- uint32_t count,
- double *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedRationalDoubleArray(tif, ndir, dir, tag,
- count, value));
- }
- static int TIFFWriteDirectoryTagSrationalDoubleArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag,
- uint32_t count,
- double *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedSrationalDoubleArray(
- tif, ndir, dir, tag, count, value));
- }
- static int TIFFWriteDirectoryTagFloatArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, float *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedFloatArray(tif, ndir, dir, tag, count,
- value));
- }
- static int TIFFWriteDirectoryTagDoubleArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, double *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedDoubleArray(tif, ndir, dir, tag, count,
- value));
- }
- static int TIFFWriteDirectoryTagIfdArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint32_t *value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- return (TIFFWriteDirectoryTagCheckedIfdArray(tif, ndir, dir, tag, count,
- value));
- }
- static int TIFFWriteDirectoryTagShortLong(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t value)
- {
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- if (value <= 0xFFFF)
- return (TIFFWriteDirectoryTagCheckedShort(tif, ndir, dir, tag,
- (uint16_t)value));
- else
- return (TIFFWriteDirectoryTagCheckedLong(tif, ndir, dir, tag, value));
- }
- static int _WriteAsType(TIFF *tif, uint64_t strile_size,
- uint64_t uncompressed_threshold)
- {
- const uint16_t compression = tif->tif_dir.td_compression;
- if (compression == COMPRESSION_NONE)
- {
- return strile_size > uncompressed_threshold;
- }
- else if (compression == COMPRESSION_JPEG ||
- compression == COMPRESSION_LZW ||
- compression == COMPRESSION_ADOBE_DEFLATE ||
- compression == COMPRESSION_DEFLATE ||
- compression == COMPRESSION_LZMA ||
- compression == COMPRESSION_LERC ||
- compression == COMPRESSION_ZSTD ||
- compression == COMPRESSION_WEBP || compression == COMPRESSION_JXL)
- {
- /* For a few select compression types, we assume that in the worst */
- /* case the compressed size will be 10 times the uncompressed size */
- /* This is overly pessismistic ! */
- return strile_size >= uncompressed_threshold / 10;
- }
- return 1;
- }
- static int WriteAsLong8(TIFF *tif, uint64_t strile_size)
- {
- return _WriteAsType(tif, strile_size, 0xFFFFFFFFU);
- }
- static int WriteAsLong4(TIFF *tif, uint64_t strile_size)
- {
- return _WriteAsType(tif, strile_size, 0xFFFFU);
- }
- /************************************************************************/
- /* TIFFWriteDirectoryTagLongLong8Array() */
- /* */
- /* Write out LONG8 array and write a SHORT/LONG/LONG8 depending */
- /* on strile size and Classic/BigTIFF mode. */
- /************************************************************************/
- static int TIFFWriteDirectoryTagLongLong8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint64_t *value)
- {
- static const char module[] = "TIFFWriteDirectoryTagLongLong8Array";
- int o;
- int write_aslong4;
- /* is this just a counting pass? */
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- if (tif->tif_dir.td_deferstrilearraywriting)
- {
- return TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_NOTYPE, 0, 0,
- NULL);
- }
- if (tif->tif_flags & TIFF_BIGTIFF)
- {
- int write_aslong8 = 1;
- /* In the case of ByteCounts array, we may be able to write them on */
- /* LONG if the strip/tilesize is not too big. */
- /* Also do that for count > 1 in the case someone would want to create
- */
- /* a single-strip file with a growing height, in which case using */
- /* LONG8 will be safer. */
- if (count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS)
- {
- write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif));
- }
- else if (count > 1 && tag == TIFFTAG_TILEBYTECOUNTS)
- {
- write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif));
- }
- if (write_aslong8)
- {
- return TIFFWriteDirectoryTagCheckedLong8Array(tif, ndir, dir, tag,
- count, value);
- }
- }
- write_aslong4 = 1;
- if (count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS)
- {
- write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif));
- }
- else if (count > 1 && tag == TIFFTAG_TILEBYTECOUNTS)
- {
- write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif));
- }
- if (write_aslong4)
- {
- /*
- ** For classic tiff we want to verify everything is in range for LONG
- ** and convert to long format.
- */
- uint32_t *p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
- uint32_t *q;
- uint64_t *ma;
- uint32_t mb;
- if (p == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- for (q = p, ma = value, mb = 0; mb < count; ma++, mb++, q++)
- {
- if (*ma > 0xFFFFFFFF)
- {
- TIFFErrorExtR(tif, module,
- "Attempt to write value larger than 0xFFFFFFFF "
- "in LONG array.");
- _TIFFfreeExt(tif, p);
- return (0);
- }
- *q = (uint32_t)(*ma);
- }
- o = TIFFWriteDirectoryTagCheckedLongArray(tif, ndir, dir, tag, count,
- p);
- _TIFFfreeExt(tif, p);
- }
- else
- {
- uint16_t *p = _TIFFmallocExt(tif, count * sizeof(uint16_t));
- uint16_t *q;
- uint64_t *ma;
- uint32_t mb;
- if (p == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- for (q = p, ma = value, mb = 0; mb < count; ma++, mb++, q++)
- {
- if (*ma > 0xFFFF)
- {
- /* Should not happen normally given the check we did before */
- TIFFErrorExtR(tif, module,
- "Attempt to write value larger than 0xFFFF in "
- "SHORT array.");
- _TIFFfreeExt(tif, p);
- return (0);
- }
- *q = (uint16_t)(*ma);
- }
- o = TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, tag, count,
- p);
- _TIFFfreeExt(tif, p);
- }
- return (o);
- }
- /************************************************************************/
- /* TIFFWriteDirectoryTagIfdIfd8Array() */
- /* */
- /* Write either IFD8 or IFD array depending on file type. */
- /************************************************************************/
- static int TIFFWriteDirectoryTagIfdIfd8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint64_t *value)
- {
- static const char module[] = "TIFFWriteDirectoryTagIfdIfd8Array";
- uint64_t *ma;
- uint32_t mb;
- uint32_t *p;
- uint32_t *q;
- int o;
- /* is this just a counting pass? */
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- /* We always write IFD8 for BigTIFF, no checking needed. */
- if (tif->tif_flags & TIFF_BIGTIFF)
- return TIFFWriteDirectoryTagCheckedIfd8Array(tif, ndir, dir, tag, count,
- value);
- /*
- ** For classic tiff we want to verify everything is in range for IFD
- ** and convert to long format.
- */
- p = _TIFFmallocExt(tif, count * sizeof(uint32_t));
- if (p == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- for (q = p, ma = value, mb = 0; mb < count; ma++, mb++, q++)
- {
- if (*ma > 0xFFFFFFFF)
- {
- TIFFErrorExtR(tif, module,
- "Attempt to write value larger than 0xFFFFFFFF in "
- "Classic TIFF file.");
- _TIFFfreeExt(tif, p);
- return (0);
- }
- *q = (uint32_t)(*ma);
- }
- o = TIFFWriteDirectoryTagCheckedIfdArray(tif, ndir, dir, tag, count, p);
- _TIFFfreeExt(tif, p);
- return (o);
- }
- static int TIFFWriteDirectoryTagColormap(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir)
- {
- static const char module[] = "TIFFWriteDirectoryTagColormap";
- uint32_t m;
- uint16_t *n;
- int o;
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- m = (1 << tif->tif_dir.td_bitspersample);
- n = _TIFFmallocExt(tif, 3 * m * sizeof(uint16_t));
- if (n == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- _TIFFmemcpy(&n[0], tif->tif_dir.td_colormap[0], m * sizeof(uint16_t));
- _TIFFmemcpy(&n[m], tif->tif_dir.td_colormap[1], m * sizeof(uint16_t));
- _TIFFmemcpy(&n[2 * m], tif->tif_dir.td_colormap[2], m * sizeof(uint16_t));
- o = TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, TIFFTAG_COLORMAP,
- 3 * m, n);
- _TIFFfreeExt(tif, n);
- return (o);
- }
- static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir)
- {
- static const char module[] = "TIFFWriteDirectoryTagTransferfunction";
- uint32_t m;
- uint16_t n;
- uint16_t *o;
- int p;
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- /* TIFFTAG_TRANSFERFUNCTION expects (1 or 3) pointer to arrays with
- * (1 << BitsPerSample) * uint16_t values.
- */
- m = (1 << tif->tif_dir.td_bitspersample);
- /* clang-format off */
- n = (tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples) > 1 ? 3 : 1;
- /* clang-format on */
- /* Check for proper number of transferfunctions */
- for (int i = 0; i < n; i++)
- {
- if (tif->tif_dir.td_transferfunction[i] == NULL)
- {
- TIFFWarningExtR(
- tif, module,
- "Too few TransferFunctions provided. Tag not written to file");
- return (1); /* Not an error; only tag is not written. */
- }
- }
- /*
- * Check if the table can be written as a single column,
- * or if it must be written as 3 columns. Note that we
- * write a 3-column tag if there are 2 samples/pixel and
- * a single column of data won't suffice--hmm.
- */
- if (n == 3)
- {
- if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],
- tif->tif_dir.td_transferfunction[2],
- m * sizeof(uint16_t)) &&
- !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],
- tif->tif_dir.td_transferfunction[1],
- m * sizeof(uint16_t)))
- n = 1;
- }
- o = _TIFFmallocExt(tif, n * m * sizeof(uint16_t));
- if (o == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- _TIFFmemcpy(&o[0], tif->tif_dir.td_transferfunction[0],
- m * sizeof(uint16_t));
- if (n > 1)
- _TIFFmemcpy(&o[m], tif->tif_dir.td_transferfunction[1],
- m * sizeof(uint16_t));
- if (n > 2)
- _TIFFmemcpy(&o[2 * m], tif->tif_dir.td_transferfunction[2],
- m * sizeof(uint16_t));
- p = TIFFWriteDirectoryTagCheckedShortArray(
- tif, ndir, dir, TIFFTAG_TRANSFERFUNCTION, n * m, o);
- _TIFFfreeExt(tif, o);
- return (p);
- }
- static int TIFFWriteDirectoryTagSubifd(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir)
- {
- static const char module[] = "TIFFWriteDirectoryTagSubifd";
- uint64_t m;
- int n;
- if (tif->tif_dir.td_nsubifd == 0)
- return (1);
- if (dir == NULL)
- {
- (*ndir)++;
- return (1);
- }
- m = tif->tif_dataoff;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- uint32_t *o;
- uint64_t *pa;
- uint32_t *pb;
- uint16_t p;
- o = _TIFFmallocExt(tif, tif->tif_dir.td_nsubifd * sizeof(uint32_t));
- if (o == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- pa = tif->tif_dir.td_subifd;
- pb = o;
- for (p = 0; p < tif->tif_dir.td_nsubifd; p++)
- {
- assert(pa != 0);
- /* Could happen if an classicTIFF has a SubIFD of type LONG8 (which
- * is illegal) */
- if (*pa > 0xFFFFFFFFUL)
- {
- TIFFErrorExtR(tif, module, "Illegal value for SubIFD tag");
- _TIFFfreeExt(tif, o);
- return (0);
- }
- *pb++ = (uint32_t)(*pa++);
- }
- n = TIFFWriteDirectoryTagCheckedIfdArray(tif, ndir, dir, TIFFTAG_SUBIFD,
- tif->tif_dir.td_nsubifd, o);
- _TIFFfreeExt(tif, o);
- }
- else
- n = TIFFWriteDirectoryTagCheckedIfd8Array(
- tif, ndir, dir, TIFFTAG_SUBIFD, tif->tif_dir.td_nsubifd,
- tif->tif_dir.td_subifd);
- if (!n)
- return (0);
- /*
- * Total hack: if this directory includes a SubIFD
- * tag then force the next <n> directories to be
- * written as ``sub directories'' of this one. This
- * is used to write things like thumbnails and
- * image masks that one wants to keep out of the
- * normal directory linkage access mechanism.
- */
- tif->tif_flags |= TIFF_INSUBIFD;
- tif->tif_nsubifd = tif->tif_dir.td_nsubifd;
- if (tif->tif_dir.td_nsubifd == 1)
- tif->tif_subifdoff = 0;
- else
- tif->tif_subifdoff = m;
- return (1);
- }
- static int TIFFWriteDirectoryTagCheckedAscii(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, char *value)
- {
- assert(sizeof(char) == 1);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_ASCII, count,
- count, value));
- }
- static int TIFFWriteDirectoryTagCheckedUndefinedArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag,
- uint32_t count,
- uint8_t *value)
- {
- assert(sizeof(uint8_t) == 1);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_UNDEFINED,
- count, count, value));
- }
- static int TIFFWriteDirectoryTagCheckedByteArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- uint8_t *value)
- {
- assert(sizeof(uint8_t) == 1);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_BYTE, count,
- count, value));
- }
- static int TIFFWriteDirectoryTagCheckedSbyteArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- int8_t *value)
- {
- assert(sizeof(int8_t) == 1);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SBYTE, count,
- count, value));
- }
- static int TIFFWriteDirectoryTagCheckedShort(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint16_t value)
- {
- uint16_t m;
- assert(sizeof(uint16_t) == 2);
- m = value;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(&m);
- return (
- TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SHORT, 1, 2, &m));
- }
- static int TIFFWriteDirectoryTagCheckedShortArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- uint16_t *value)
- {
- assert(count < 0x80000000);
- assert(sizeof(uint16_t) == 2);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfShort(value, count);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SHORT, count,
- count * 2, value));
- }
- static int TIFFWriteDirectoryTagCheckedSshortArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- int16_t *value)
- {
- assert(count < 0x80000000);
- assert(sizeof(int16_t) == 2);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfShort((uint16_t *)value, count);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SSHORT, count,
- count * 2, value));
- }
- static int TIFFWriteDirectoryTagCheckedLong(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t value)
- {
- uint32_t m;
- assert(sizeof(uint32_t) == 4);
- m = value;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&m);
- return (
- TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_LONG, 1, 4, &m));
- }
- static int TIFFWriteDirectoryTagCheckedLongArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- uint32_t *value)
- {
- assert(count < 0x40000000);
- assert(sizeof(uint32_t) == 4);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong(value, count);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_LONG, count,
- count * 4, value));
- }
- static int TIFFWriteDirectoryTagCheckedSlongArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- int32_t *value)
- {
- assert(count < 0x40000000);
- assert(sizeof(int32_t) == 4);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong((uint32_t *)value, count);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SLONG, count,
- count * 4, value));
- }
- static int TIFFWriteDirectoryTagCheckedLong8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- uint64_t *value)
- {
- assert(count < 0x20000000);
- assert(sizeof(uint64_t) == 8);
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- TIFFErrorExtR(tif, "TIFFWriteDirectoryTagCheckedLong8Array",
- "LONG8 not allowed for ClassicTIFF");
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong8(value, count);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_LONG8, count,
- count * 8, value));
- }
- static int TIFFWriteDirectoryTagCheckedSlong8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- int64_t *value)
- {
- assert(count < 0x20000000);
- assert(sizeof(int64_t) == 8);
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- TIFFErrorExtR(tif, "TIFFWriteDirectoryTagCheckedSlong8Array",
- "SLONG8 not allowed for ClassicTIFF");
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong8((uint64_t *)value, count);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SLONG8, count,
- count * 8, value));
- }
- static int TIFFWriteDirectoryTagCheckedRational(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- double value)
- {
- static const char module[] = "TIFFWriteDirectoryTagCheckedRational";
- uint32_t m[2];
- assert(sizeof(uint32_t) == 4);
- if (value < 0)
- {
- TIFFErrorExtR(tif, module, "Negative value is illegal");
- return 0;
- }
- else if (value != value)
- {
- TIFFErrorExtR(tif, module, "Not-a-number value is illegal");
- return 0;
- }
- /*--Rational2Double: New function also used for non-custom rational tags.
- * However, could be omitted here, because
- * TIFFWriteDirectoryTagCheckedRational() is not used by code for custom
- * tags, only by code for named-tiff-tags like FIELD_RESOLUTION and
- * FIELD_POSITION */
- else
- {
- DoubleToRational(value, &m[0], &m[1]);
- }
- if (tif->tif_flags & TIFF_SWAB)
- {
- TIFFSwabLong(&m[0]);
- TIFFSwabLong(&m[1]);
- }
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_RATIONAL, 1, 8,
- &m[0]));
- }
- static int TIFFWriteDirectoryTagCheckedRationalArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag,
- uint32_t count,
- float *value)
- {
- static const char module[] = "TIFFWriteDirectoryTagCheckedRationalArray";
- uint32_t *m;
- float *na;
- uint32_t *nb;
- uint32_t nc;
- int o;
- assert(sizeof(uint32_t) == 4);
- m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t));
- if (m == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
- {
- DoubleToRational(*na, &nb[0], &nb[1]);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong(m, count * 2);
- o = TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_RATIONAL, count,
- count * 8, &m[0]);
- _TIFFfreeExt(tif, m);
- return (o);
- }
- static int TIFFWriteDirectoryTagCheckedSrationalArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag,
- uint32_t count,
- float *value)
- {
- static const char module[] = "TIFFWriteDirectoryTagCheckedSrationalArray";
- int32_t *m;
- float *na;
- int32_t *nb;
- uint32_t nc;
- int o;
- assert(sizeof(int32_t) == 4);
- m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t));
- if (m == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
- {
- DoubleToSrational(*na, &nb[0], &nb[1]);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong((uint32_t *)m, count * 2);
- o = TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SRATIONAL, count,
- count * 8, &m[0]);
- _TIFFfreeExt(tif, m);
- return (o);
- }
- /*-- Rational2Double: additional write functions for double arrays */
- static int
- TIFFWriteDirectoryTagCheckedRationalDoubleArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, double *value)
- {
- static const char module[] =
- "TIFFWriteDirectoryTagCheckedRationalDoubleArray";
- uint32_t *m;
- double *na;
- uint32_t *nb;
- uint32_t nc;
- int o;
- assert(sizeof(uint32_t) == 4);
- m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t));
- if (m == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
- {
- DoubleToRational(*na, &nb[0], &nb[1]);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong(m, count * 2);
- o = TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_RATIONAL, count,
- count * 8, &m[0]);
- _TIFFfreeExt(tif, m);
- return (o);
- } /*-- TIFFWriteDirectoryTagCheckedRationalDoubleArray() ------- */
- static int TIFFWriteDirectoryTagCheckedSrationalDoubleArray(
- TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count,
- double *value)
- {
- static const char module[] =
- "TIFFWriteDirectoryTagCheckedSrationalDoubleArray";
- int32_t *m;
- double *na;
- int32_t *nb;
- uint32_t nc;
- int o;
- assert(sizeof(int32_t) == 4);
- m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t));
- if (m == NULL)
- {
- TIFFErrorExtR(tif, module, "Out of memory");
- return (0);
- }
- for (na = value, nb = m, nc = 0; nc < count; na++, nb += 2, nc++)
- {
- DoubleToSrational(*na, &nb[0], &nb[1]);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong((uint32_t *)m, count * 2);
- o = TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SRATIONAL, count,
- count * 8, &m[0]);
- _TIFFfreeExt(tif, m);
- return (o);
- } /*--- TIFFWriteDirectoryTagCheckedSrationalDoubleArray() -------- */
- /** ----- Rational2Double: Double To Rational Conversion
- ----------------------------------------------------------
- * There is a mathematical theorem to convert real numbers into a rational
- (integer fraction) number.
- * This is called "continuous fraction" which uses the Euclidean algorithm to
- find the greatest common divisor (GCD).
- * (ref. e.g. https://de.wikipedia.org/wiki/Kettenbruch or
- https://en.wikipedia.org/wiki/Continued_fraction
- * https://en.wikipedia.org/wiki/Euclidean_algorithm)
- * The following functions implement the
- * - ToRationalEuclideanGCD() auxiliary function which mainly
- implements euclidean GCD
- * - DoubleToRational() conversion function for un-signed
- rationals
- * - DoubleToSrational() conversion function for signed rationals
- ------------------------------------------------------------------------------------------------------------------*/
- /**---- ToRationalEuclideanGCD() -----------------------------------------
- * Calculates the rational fractional of a double input value
- * using the Euclidean algorithm to find the greatest common divisor (GCD)
- ------------------------------------------------------------------------*/
- static void ToRationalEuclideanGCD(double value, int blnUseSignedRange,
- int blnUseSmallRange, uint64_t *ullNum,
- uint64_t *ullDenom)
- {
- /* Internally, the integer variables can be bigger than the external ones,
- * as long as the result will fit into the external variable size.
- */
- uint64_t numSum[3] = {0, 1, 0}, denomSum[3] = {1, 0, 0};
- uint64_t aux, bigNum, bigDenom;
- uint64_t returnLimit;
- int i;
- uint64_t nMax;
- double fMax;
- unsigned long maxDenom;
- /*-- nMax and fMax defines the initial accuracy of the starting fractional,
- * or better, the highest used integer numbers used within the starting
- * fractional (bigNum/bigDenom). There are two approaches, which can
- * accidentally lead to different accuracies just depending on the value.
- * Therefore, blnUseSmallRange steers this behavior.
- * For long long nMax = ((9223372036854775807-1)/2); for long nMax =
- * ((2147483647-1)/2);
- */
- if (blnUseSmallRange)
- {
- nMax = (uint64_t)((2147483647 - 1) / 2); /* for ULONG range */
- }
- else
- {
- nMax = ((9223372036854775807 - 1) / 2); /* for ULLONG range */
- }
- fMax = (double)nMax;
- /*-- For the Euclidean GCD define the denominator range, so that it stays
- * within size of unsigned long variables. maxDenom should be LONG_MAX for
- * negative values and ULONG_MAX for positive ones. Also the final returned
- * value of ullNum and ullDenom is limited according to signed- or
- * unsigned-range.
- */
- if (blnUseSignedRange)
- {
- maxDenom = 2147483647UL; /*LONG_MAX = 0x7FFFFFFFUL*/
- returnLimit = maxDenom;
- }
- else
- {
- maxDenom = 0xFFFFFFFFUL; /*ULONG_MAX = 0xFFFFFFFFUL*/
- returnLimit = maxDenom;
- }
- /*-- First generate a rational fraction (bigNum/bigDenom) which represents
- *the value as a rational number with the highest accuracy. Therefore,
- *uint64_t (uint64_t) is needed. This rational fraction is then reduced
- *using the Euclidean algorithm to find the greatest common divisor (GCD).
- * bigNum = big numinator of value without fraction (or cut residual
- *fraction) bigDenom = big denominator of value
- *-- Break-criteria so that uint64_t cast to "bigNum" introduces no error
- *and bigDenom has no overflow, and stop with enlargement of fraction when
- *the double-value of it reaches an integer number without fractional part.
- */
- bigDenom = 1;
- while ((value != floor(value)) && (value < fMax) && (bigDenom < nMax))
- {
- bigDenom <<= 1;
- value *= 2;
- }
- bigNum = (uint64_t)value;
- /*-- Start Euclidean algorithm to find the greatest common divisor (GCD) --
- */
- #define MAX_ITERATIONS 64
- for (i = 0; i < MAX_ITERATIONS; i++)
- {
- uint64_t val;
- /* if bigDenom is not zero, calculate integer part of fraction. */
- if (bigDenom == 0)
- {
- break;
- }
- val = bigNum / bigDenom;
- /* Set bigDenom to reminder of bigNum/bigDenom and bigNum to previous
- * denominator bigDenom. */
- aux = bigNum;
- bigNum = bigDenom;
- bigDenom = aux % bigDenom;
- /* calculate next denominator and check for its given maximum */
- aux = val;
- if (denomSum[1] * val + denomSum[0] >= maxDenom)
- {
- aux = (maxDenom - denomSum[0]) / denomSum[1];
- if (aux * 2 >= val || denomSum[1] >= maxDenom)
- i = (MAX_ITERATIONS +
- 1); /* exit but execute rest of for-loop */
- else
- break;
- }
- /* calculate next numerator to numSum2 and save previous one to numSum0;
- * numSum1 just copy of numSum2. */
- numSum[2] = aux * numSum[1] + numSum[0];
- numSum[0] = numSum[1];
- numSum[1] = numSum[2];
- /* calculate next denominator to denomSum2 and save previous one to
- * denomSum0; denomSum1 just copy of denomSum2. */
- denomSum[2] = aux * denomSum[1] + denomSum[0];
- denomSum[0] = denomSum[1];
- denomSum[1] = denomSum[2];
- }
- /*-- Check and adapt for final variable size and return values; reduces
- * internal accuracy; denominator is kept in ULONG-range with maxDenom -- */
- while (numSum[1] > returnLimit || denomSum[1] > returnLimit)
- {
- numSum[1] = numSum[1] / 2;
- denomSum[1] = denomSum[1] / 2;
- }
- /* return values */
- *ullNum = numSum[1];
- *ullDenom = denomSum[1];
- } /*-- ToRationalEuclideanGCD() -------------- */
- /**---- DoubleToRational() -----------------------------------------------
- * Calculates the rational fractional of a double input value
- * for UN-SIGNED rationals,
- * using the Euclidean algorithm to find the greatest common divisor (GCD)
- ------------------------------------------------------------------------*/
- static void DoubleToRational(double value, uint32_t *num, uint32_t *denom)
- {
- /*---- UN-SIGNED RATIONAL ---- */
- double dblDiff, dblDiff2;
- uint64_t ullNum, ullDenom, ullNum2, ullDenom2;
- /*-- Check for negative values. If so it is an error. */
- /* Test written that way to catch NaN */
- if (!(value >= 0))
- {
- *num = *denom = 0;
- TIFFErrorExt(0, "TIFFLib: DoubleToRational()",
- " Negative Value for Unsigned Rational given.");
- return;
- }
- /*-- Check for too big numbers (> ULONG_MAX) -- */
- if (value > 0xFFFFFFFFUL)
- {
- *num = 0xFFFFFFFFU;
- *denom = 0;
- return;
- }
- /*-- Check for easy integer numbers -- */
- if (value == (uint32_t)(value))
- {
- *num = (uint32_t)value;
- *denom = 1;
- return;
- }
- /*-- Check for too small numbers for "unsigned long" type rationals -- */
- if (value < 1.0 / (double)0xFFFFFFFFUL)
- {
- *num = 0;
- *denom = 0xFFFFFFFFU;
- return;
- }
- /*-- There are two approaches using the Euclidean algorithm,
- * which can accidentally lead to different accuracies just depending on
- * the value. Try both and define which one was better.
- */
- ToRationalEuclideanGCD(value, FALSE, FALSE, &ullNum, &ullDenom);
- ToRationalEuclideanGCD(value, FALSE, TRUE, &ullNum2, &ullDenom2);
- /*-- Double-Check, that returned values fit into ULONG :*/
- if (ullNum > 0xFFFFFFFFUL || ullDenom > 0xFFFFFFFFUL ||
- ullNum2 > 0xFFFFFFFFUL || ullDenom2 > 0xFFFFFFFFUL)
- {
- TIFFErrorExt(0, "TIFFLib: DoubleToRational()",
- " Num or Denom exceeds ULONG: val=%14.6f, num=%12" PRIu64
- ", denom=%12" PRIu64 " | num2=%12" PRIu64
- ", denom2=%12" PRIu64 "",
- value, ullNum, ullDenom, ullNum2, ullDenom2);
- assert(0);
- }
- /* Check, which one has higher accuracy and take that. */
- dblDiff = fabs(value - ((double)ullNum / (double)ullDenom));
- dblDiff2 = fabs(value - ((double)ullNum2 / (double)ullDenom2));
- if (dblDiff < dblDiff2)
- {
- *num = (uint32_t)ullNum;
- *denom = (uint32_t)ullDenom;
- }
- else
- {
- *num = (uint32_t)ullNum2;
- *denom = (uint32_t)ullDenom2;
- }
- } /*-- DoubleToRational() -------------- */
- /**---- DoubleToSrational() -----------------------------------------------
- * Calculates the rational fractional of a double input value
- * for SIGNED rationals,
- * using the Euclidean algorithm to find the greatest common divisor (GCD)
- ------------------------------------------------------------------------*/
- static void DoubleToSrational(double value, int32_t *num, int32_t *denom)
- {
- /*---- SIGNED RATIONAL ----*/
- int neg = 1;
- double dblDiff, dblDiff2;
- uint64_t ullNum, ullDenom, ullNum2, ullDenom2;
- /*-- Check for negative values and use then the positive one for internal
- * calculations, but take the sign into account before returning. */
- if (value < 0)
- {
- neg = -1;
- value = -value;
- }
- /*-- Check for too big numbers (> LONG_MAX) -- */
- if (value > 0x7FFFFFFFL)
- {
- *num = 0x7FFFFFFFL;
- *denom = 0;
- return;
- }
- /*-- Check for easy numbers -- */
- if (value == (int32_t)(value))
- {
- *num = (int32_t)(neg * value);
- *denom = 1;
- return;
- }
- /*-- Check for too small numbers for "long" type rationals -- */
- if (value < 1.0 / (double)0x7FFFFFFFL)
- {
- *num = 0;
- *denom = 0x7FFFFFFFL;
- return;
- }
- /*-- There are two approaches using the Euclidean algorithm,
- * which can accidentally lead to different accuracies just depending on
- * the value. Try both and define which one was better. Furthermore, set
- * behavior of ToRationalEuclideanGCD() to the range of signed-long.
- */
- ToRationalEuclideanGCD(value, TRUE, FALSE, &ullNum, &ullDenom);
- ToRationalEuclideanGCD(value, TRUE, TRUE, &ullNum2, &ullDenom2);
- /*-- Double-Check, that returned values fit into LONG :*/
- if (ullNum > 0x7FFFFFFFL || ullDenom > 0x7FFFFFFFL ||
- ullNum2 > 0x7FFFFFFFL || ullDenom2 > 0x7FFFFFFFL)
- {
- TIFFErrorExt(0, "TIFFLib: DoubleToSrational()",
- " Num or Denom exceeds LONG: val=%14.6f, num=%12" PRIu64
- ", denom=%12" PRIu64 " | num2=%12" PRIu64
- ", denom2=%12" PRIu64 "",
- neg * value, ullNum, ullDenom, ullNum2, ullDenom2);
- assert(0);
- }
- /* Check, which one has higher accuracy and take that. */
- dblDiff = fabs(value - ((double)ullNum / (double)ullDenom));
- dblDiff2 = fabs(value - ((double)ullNum2 / (double)ullDenom2));
- if (dblDiff < dblDiff2)
- {
- *num = (int32_t)(neg * (long)ullNum);
- *denom = (int32_t)ullDenom;
- }
- else
- {
- *num = (int32_t)(neg * (long)ullNum2);
- *denom = (int32_t)ullDenom2;
- }
- } /*-- DoubleToSrational() --------------*/
- static int TIFFWriteDirectoryTagCheckedFloatArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- float *value)
- {
- assert(count < 0x40000000);
- assert(sizeof(float) == 4);
- TIFFCvtNativeToIEEEFloat(tif, count, &value);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfFloat(value, count);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_FLOAT, count,
- count * 4, value));
- }
- static int TIFFWriteDirectoryTagCheckedDoubleArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- double *value)
- {
- assert(count < 0x20000000);
- assert(sizeof(double) == 8);
- TIFFCvtNativeToIEEEDouble(tif, count, &value);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfDouble(value, count);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_DOUBLE, count,
- count * 8, value));
- }
- static int TIFFWriteDirectoryTagCheckedIfdArray(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint32_t count, uint32_t *value)
- {
- assert(count < 0x40000000);
- assert(sizeof(uint32_t) == 4);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong(value, count);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_IFD, count,
- count * 4, value));
- }
- static int TIFFWriteDirectoryTagCheckedIfd8Array(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir,
- uint16_t tag, uint32_t count,
- uint64_t *value)
- {
- assert(count < 0x20000000);
- assert(sizeof(uint64_t) == 8);
- assert(tif->tif_flags & TIFF_BIGTIFF);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabArrayOfLong8(value, count);
- return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_IFD8, count,
- count * 8, value));
- }
- static int TIFFWriteDirectoryTagData(TIFF *tif, uint32_t *ndir,
- TIFFDirEntry *dir, uint16_t tag,
- uint16_t datatype, uint32_t count,
- uint32_t datalength, void *data)
- {
- static const char module[] = "TIFFWriteDirectoryTagData";
- uint32_t m;
- m = 0;
- while (m < (*ndir))
- {
- assert(dir[m].tdir_tag != tag);
- if (dir[m].tdir_tag > tag)
- break;
- m++;
- }
- if (m < (*ndir))
- {
- uint32_t n;
- for (n = *ndir; n > m; n--)
- dir[n] = dir[n - 1];
- }
- dir[m].tdir_tag = tag;
- dir[m].tdir_type = datatype;
- dir[m].tdir_count = count;
- dir[m].tdir_offset.toff_long8 = 0;
- if (datalength <= ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U))
- {
- if (data && datalength)
- {
- _TIFFmemcpy(&dir[m].tdir_offset, data, datalength);
- }
- }
- else
- {
- uint64_t na, nb;
- na = tif->tif_dataoff;
- nb = na + datalength;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- nb = (uint32_t)nb;
- if ((nb < na) || (nb < datalength))
- {
- TIFFErrorExtR(tif, module, "Maximum TIFF file size exceeded");
- return (0);
- }
- if (!SeekOK(tif, na))
- {
- TIFFErrorExtR(tif, module, "IO error writing tag data");
- return (0);
- }
- if (datalength >= 0x80000000UL)
- {
- TIFFErrorExtR(tif, module,
- "libtiff does not allow writing more than 2147483647 "
- "bytes in a tag");
- return (0);
- }
- if (!WriteOK(tif, data, (tmsize_t)datalength))
- {
- TIFFErrorExtR(tif, module, "IO error writing tag data");
- return (0);
- }
- tif->tif_dataoff = nb;
- if (tif->tif_dataoff & 1)
- tif->tif_dataoff++;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- uint32_t o;
- o = (uint32_t)na;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&o);
- _TIFFmemcpy(&dir[m].tdir_offset, &o, 4);
- }
- else
- {
- dir[m].tdir_offset.toff_long8 = na;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&dir[m].tdir_offset.toff_long8);
- }
- }
- (*ndir)++;
- return (1);
- }
- /*
- * Link the current directory into the directory chain for the file.
- */
- static int TIFFLinkDirectory(TIFF *tif)
- {
- static const char module[] = "TIFFLinkDirectory";
- tif->tif_diroff = (TIFFSeekFile(tif, 0, SEEK_END) + 1) & (~((toff_t)1));
- /*
- * Handle SubIFDs
- */
- if (tif->tif_flags & TIFF_INSUBIFD)
- {
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- uint32_t m;
- m = (uint32_t)tif->tif_diroff;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&m);
- (void)TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
- if (!WriteOK(tif, &m, 4))
- {
- TIFFErrorExtR(tif, module,
- "Error writing SubIFD directory link");
- return (0);
- }
- /*
- * Advance to the next SubIFD or, if this is
- * the last one configured, revert back to the
- * normal directory linkage.
- */
- if (--tif->tif_nsubifd)
- tif->tif_subifdoff += 4;
- else
- tif->tif_flags &= ~TIFF_INSUBIFD;
- return (1);
- }
- else
- {
- uint64_t m;
- m = tif->tif_diroff;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&m);
- (void)TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
- if (!WriteOK(tif, &m, 8))
- {
- TIFFErrorExtR(tif, module,
- "Error writing SubIFD directory link");
- return (0);
- }
- /*
- * Advance to the next SubIFD or, if this is
- * the last one configured, revert back to the
- * normal directory linkage.
- */
- if (--tif->tif_nsubifd)
- tif->tif_subifdoff += 8;
- else
- tif->tif_flags &= ~TIFF_INSUBIFD;
- return (1);
- }
- }
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- uint32_t m;
- uint32_t nextdir;
- m = (uint32_t)(tif->tif_diroff);
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&m);
- if (tif->tif_header.classic.tiff_diroff == 0)
- {
- /*
- * First directory, overwrite offset in header.
- */
- tif->tif_header.classic.tiff_diroff = (uint32_t)tif->tif_diroff;
- tif->tif_lastdiroff = tif->tif_diroff;
- (void)TIFFSeekFile(tif, 4, SEEK_SET);
- if (!WriteOK(tif, &m, 4))
- {
- TIFFErrorExtR(tif, tif->tif_name, "Error writing TIFF header");
- return (0);
- }
- return (1);
- }
- /*
- * Not the first directory, search to the last and append.
- */
- if (tif->tif_lastdiroff != 0)
- {
- nextdir = (uint32_t)tif->tif_lastdiroff;
- }
- else
- {
- nextdir = tif->tif_header.classic.tiff_diroff;
- }
- while (1)
- {
- uint16_t dircount;
- uint32_t nextnextdir;
- if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount, 2))
- {
- TIFFErrorExtR(tif, module, "Error fetching directory count");
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(&dircount);
- (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET);
- if (!ReadOK(tif, &nextnextdir, 4))
- {
- TIFFErrorExtR(tif, module, "Error fetching directory link");
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&nextnextdir);
- if (nextnextdir == 0)
- {
- (void)TIFFSeekFile(tif, nextdir + 2 + dircount * 12, SEEK_SET);
- if (!WriteOK(tif, &m, 4))
- {
- TIFFErrorExtR(tif, module, "Error writing directory link");
- return (0);
- }
- tif->tif_lastdiroff = tif->tif_diroff;
- break;
- }
- nextdir = nextnextdir;
- }
- }
- else
- {
- uint64_t m;
- uint64_t nextdir;
- m = tif->tif_diroff;
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&m);
- if (tif->tif_header.big.tiff_diroff == 0)
- {
- /*
- * First directory, overwrite offset in header.
- */
- tif->tif_header.big.tiff_diroff = tif->tif_diroff;
- tif->tif_lastdiroff = tif->tif_diroff;
- (void)TIFFSeekFile(tif, 8, SEEK_SET);
- if (!WriteOK(tif, &m, 8))
- {
- TIFFErrorExtR(tif, tif->tif_name, "Error writing TIFF header");
- return (0);
- }
- return (1);
- }
- /*
- * Not the first directory, search to the last and append.
- */
- if (tif->tif_lastdiroff != 0)
- {
- nextdir = tif->tif_lastdiroff;
- }
- else
- {
- nextdir = tif->tif_header.big.tiff_diroff;
- }
- while (1)
- {
- uint64_t dircount64;
- uint16_t dircount;
- uint64_t nextnextdir;
- if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount64, 8))
- {
- TIFFErrorExtR(tif, module, "Error fetching directory count");
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&dircount64);
- if (dircount64 > 0xFFFF)
- {
- TIFFErrorExtR(
- tif, module,
- "Sanity check on tag count failed, likely corrupt TIFF");
- return (0);
- }
- dircount = (uint16_t)dircount64;
- (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET);
- if (!ReadOK(tif, &nextnextdir, 8))
- {
- TIFFErrorExtR(tif, module, "Error fetching directory link");
- return (0);
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&nextnextdir);
- if (nextnextdir == 0)
- {
- (void)TIFFSeekFile(tif, nextdir + 8 + dircount * 20, SEEK_SET);
- if (!WriteOK(tif, &m, 8))
- {
- TIFFErrorExtR(tif, module, "Error writing directory link");
- return (0);
- }
- tif->tif_lastdiroff = tif->tif_diroff;
- break;
- }
- nextdir = nextnextdir;
- }
- }
- return (1);
- }
- /************************************************************************/
- /* TIFFRewriteField() */
- /* */
- /* Rewrite a field in the directory on disk without regard to */
- /* updating the TIFF directory structure in memory. Currently */
- /* only supported for field that already exist in the on-disk */
- /* directory. Mainly used for updating stripoffset / */
- /* stripbytecount values after the directory is already on */
- /* disk. */
- /* */
- /* Returns zero on failure, and one on success. */
- /************************************************************************/
- int _TIFFRewriteField(TIFF *tif, uint16_t tag, TIFFDataType in_datatype,
- tmsize_t count, void *data)
- {
- static const char module[] = "TIFFResetField";
- /* const TIFFField* fip = NULL; */
- uint16_t dircount;
- tmsize_t dirsize;
- uint8_t direntry_raw[20];
- uint16_t entry_tag = 0;
- uint16_t entry_type = 0;
- uint64_t entry_count = 0;
- uint64_t entry_offset = 0;
- int value_in_entry = 0;
- uint64_t read_offset;
- uint8_t *buf_to_write = NULL;
- TIFFDataType datatype;
- /* -------------------------------------------------------------------- */
- /* Find field definition. */
- /* -------------------------------------------------------------------- */
- /*fip =*/TIFFFindField(tif, tag, TIFF_ANY);
- /* -------------------------------------------------------------------- */
- /* Do some checking this is a straight forward case. */
- /* -------------------------------------------------------------------- */
- if (isMapped(tif))
- {
- TIFFErrorExtR(
- tif, module,
- "Memory mapped files not currently supported for this operation.");
- return 0;
- }
- if (tif->tif_diroff == 0)
- {
- TIFFErrorExtR(
- tif, module,
- "Attempt to reset field on directory not already on disk.");
- return 0;
- }
- /* -------------------------------------------------------------------- */
- /* Read the directory entry count. */
- /* -------------------------------------------------------------------- */
- if (!SeekOK(tif, tif->tif_diroff))
- {
- TIFFErrorExtR(tif, module, "%s: Seek error accessing TIFF directory",
- tif->tif_name);
- return 0;
- }
- read_offset = tif->tif_diroff;
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- if (!ReadOK(tif, &dircount, sizeof(uint16_t)))
- {
- TIFFErrorExtR(tif, module, "%s: Can not read TIFF directory count",
- tif->tif_name);
- return 0;
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(&dircount);
- dirsize = 12;
- read_offset += 2;
- }
- else
- {
- uint64_t dircount64;
- if (!ReadOK(tif, &dircount64, sizeof(uint64_t)))
- {
- TIFFErrorExtR(tif, module, "%s: Can not read TIFF directory count",
- tif->tif_name);
- return 0;
- }
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&dircount64);
- dircount = (uint16_t)dircount64;
- dirsize = 20;
- read_offset += 8;
- }
- /* -------------------------------------------------------------------- */
- /* Read through directory to find target tag. */
- /* -------------------------------------------------------------------- */
- while (dircount > 0)
- {
- if (!ReadOK(tif, direntry_raw, dirsize))
- {
- TIFFErrorExtR(tif, module, "%s: Can not read TIFF directory entry.",
- tif->tif_name);
- return 0;
- }
- memcpy(&entry_tag, direntry_raw + 0, sizeof(uint16_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(&entry_tag);
- if (entry_tag == tag)
- break;
- read_offset += dirsize;
- }
- if (entry_tag != tag)
- {
- TIFFErrorExtR(tif, module, "%s: Could not find tag %" PRIu16 ".",
- tif->tif_name, tag);
- return 0;
- }
- /* -------------------------------------------------------------------- */
- /* Extract the type, count and offset for this entry. */
- /* -------------------------------------------------------------------- */
- memcpy(&entry_type, direntry_raw + 2, sizeof(uint16_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort(&entry_type);
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- uint32_t value;
- memcpy(&value, direntry_raw + 4, sizeof(uint32_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&value);
- entry_count = value;
- memcpy(&value, direntry_raw + 8, sizeof(uint32_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong(&value);
- entry_offset = value;
- }
- else
- {
- memcpy(&entry_count, direntry_raw + 4, sizeof(uint64_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&entry_count);
- memcpy(&entry_offset, direntry_raw + 12, sizeof(uint64_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8(&entry_offset);
- }
- /* -------------------------------------------------------------------- */
- /* When a dummy tag was written due to TIFFDeferStrileArrayWriting() */
- /* -------------------------------------------------------------------- */
- if (entry_offset == 0 && entry_count == 0 && entry_type == 0)
- {
- if (tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS)
- {
- entry_type =
- (tif->tif_flags & TIFF_BIGTIFF) ? TIFF_LONG8 : TIFF_LONG;
- }
- else
- {
- int write_aslong8 = 1;
- if (count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS)
- {
- write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif));
- }
- else if (count > 1 && tag == TIFFTAG_TILEBYTECOUNTS)
- {
- write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif));
- }
- if (write_aslong8)
- {
- entry_type = TIFF_LONG8;
- }
- else
- {
- int write_aslong4 = 1;
- if (count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS)
- {
- write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif));
- }
- else if (count > 1 && tag == TIFFTAG_TILEBYTECOUNTS)
- {
- write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif));
- }
- if (write_aslong4)
- {
- entry_type = TIFF_LONG;
- }
- else
- {
- entry_type = TIFF_SHORT;
- }
- }
- }
- }
- /* -------------------------------------------------------------------- */
- /* What data type do we want to write this as? */
- /* -------------------------------------------------------------------- */
- if (TIFFDataWidth(in_datatype) == 8 && !(tif->tif_flags & TIFF_BIGTIFF))
- {
- if (in_datatype == TIFF_LONG8)
- datatype = entry_type == TIFF_SHORT ? TIFF_SHORT : TIFF_LONG;
- else if (in_datatype == TIFF_SLONG8)
- datatype = TIFF_SLONG;
- else if (in_datatype == TIFF_IFD8)
- datatype = TIFF_IFD;
- else
- datatype = in_datatype;
- }
- else
- {
- if (in_datatype == TIFF_LONG8 &&
- (entry_type == TIFF_SHORT || entry_type == TIFF_LONG ||
- entry_type == TIFF_LONG8))
- datatype = entry_type;
- else if (in_datatype == TIFF_SLONG8 &&
- (entry_type == TIFF_SLONG || entry_type == TIFF_SLONG8))
- datatype = entry_type;
- else if (in_datatype == TIFF_IFD8 &&
- (entry_type == TIFF_IFD || entry_type == TIFF_IFD8))
- datatype = entry_type;
- else
- datatype = in_datatype;
- }
- /* -------------------------------------------------------------------- */
- /* Prepare buffer of actual data to write. This includes */
- /* swabbing as needed. */
- /* -------------------------------------------------------------------- */
- buf_to_write = (uint8_t *)_TIFFCheckMalloc(
- tif, count, TIFFDataWidth(datatype), "for field buffer.");
- if (!buf_to_write)
- return 0;
- if (datatype == in_datatype)
- memcpy(buf_to_write, data, count * TIFFDataWidth(datatype));
- else if (datatype == TIFF_SLONG && in_datatype == TIFF_SLONG8)
- {
- tmsize_t i;
- for (i = 0; i < count; i++)
- {
- ((int32_t *)buf_to_write)[i] = (int32_t)((int64_t *)data)[i];
- if ((int64_t)((int32_t *)buf_to_write)[i] != ((int64_t *)data)[i])
- {
- _TIFFfreeExt(tif, buf_to_write);
- TIFFErrorExtR(tif, module,
- "Value exceeds 32bit range of output type.");
- return 0;
- }
- }
- }
- else if ((datatype == TIFF_LONG && in_datatype == TIFF_LONG8) ||
- (datatype == TIFF_IFD && in_datatype == TIFF_IFD8))
- {
- tmsize_t i;
- for (i = 0; i < count; i++)
- {
- ((uint32_t *)buf_to_write)[i] = (uint32_t)((uint64_t *)data)[i];
- if ((uint64_t)((uint32_t *)buf_to_write)[i] !=
- ((uint64_t *)data)[i])
- {
- _TIFFfreeExt(tif, buf_to_write);
- TIFFErrorExtR(tif, module,
- "Value exceeds 32bit range of output type.");
- return 0;
- }
- }
- }
- else if (datatype == TIFF_SHORT && in_datatype == TIFF_LONG8)
- {
- tmsize_t i;
- for (i = 0; i < count; i++)
- {
- ((uint16_t *)buf_to_write)[i] = (uint16_t)((uint64_t *)data)[i];
- if ((uint64_t)((uint16_t *)buf_to_write)[i] !=
- ((uint64_t *)data)[i])
- {
- _TIFFfreeExt(tif, buf_to_write);
- TIFFErrorExtR(tif, module,
- "Value exceeds 16bit range of output type.");
- return 0;
- }
- }
- }
- else
- {
- TIFFErrorExtR(tif, module, "Unhandled type conversion.");
- return 0;
- }
- if (TIFFDataWidth(datatype) > 1 && (tif->tif_flags & TIFF_SWAB))
- {
- if (TIFFDataWidth(datatype) == 2)
- TIFFSwabArrayOfShort((uint16_t *)buf_to_write, count);
- else if (TIFFDataWidth(datatype) == 4)
- TIFFSwabArrayOfLong((uint32_t *)buf_to_write, count);
- else if (TIFFDataWidth(datatype) == 8)
- TIFFSwabArrayOfLong8((uint64_t *)buf_to_write, count);
- }
- /* -------------------------------------------------------------------- */
- /* Is this a value that fits into the directory entry? */
- /* -------------------------------------------------------------------- */
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- if (TIFFDataWidth(datatype) * count <= 4)
- {
- entry_offset = read_offset + 8;
- value_in_entry = 1;
- }
- }
- else
- {
- if (TIFFDataWidth(datatype) * count <= 8)
- {
- entry_offset = read_offset + 12;
- value_in_entry = 1;
- }
- }
- if ((tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS) &&
- tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
- tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
- tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0)
- {
- tif->tif_dir.td_stripoffset_entry.tdir_type = datatype;
- tif->tif_dir.td_stripoffset_entry.tdir_count = count;
- }
- else if ((tag == TIFFTAG_TILEBYTECOUNTS ||
- tag == TIFFTAG_STRIPBYTECOUNTS) &&
- tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
- tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
- tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0)
- {
- tif->tif_dir.td_stripbytecount_entry.tdir_type = datatype;
- tif->tif_dir.td_stripbytecount_entry.tdir_count = count;
- }
- /* -------------------------------------------------------------------- */
- /* If the tag type, and count match, then we just write it out */
- /* over the old values without altering the directory entry at */
- /* all. */
- /* -------------------------------------------------------------------- */
- if (entry_count == (uint64_t)count && entry_type == (uint16_t)datatype)
- {
- if (!SeekOK(tif, entry_offset))
- {
- _TIFFfreeExt(tif, buf_to_write);
- TIFFErrorExtR(tif, module,
- "%s: Seek error accessing TIFF directory",
- tif->tif_name);
- return 0;
- }
- if (!WriteOK(tif, buf_to_write, count * TIFFDataWidth(datatype)))
- {
- _TIFFfreeExt(tif, buf_to_write);
- TIFFErrorExtR(tif, module, "Error writing directory link");
- return (0);
- }
- _TIFFfreeExt(tif, buf_to_write);
- return 1;
- }
- /* -------------------------------------------------------------------- */
- /* Otherwise, we write the new tag data at the end of the file. */
- /* -------------------------------------------------------------------- */
- if (!value_in_entry)
- {
- entry_offset = TIFFSeekFile(tif, 0, SEEK_END);
- if (!WriteOK(tif, buf_to_write, count * TIFFDataWidth(datatype)))
- {
- _TIFFfreeExt(tif, buf_to_write);
- TIFFErrorExtR(tif, module, "Error writing directory link");
- return (0);
- }
- }
- else
- {
- if (count * TIFFDataWidth(datatype) == 4)
- {
- uint32_t value;
- memcpy(&value, buf_to_write, count * TIFFDataWidth(datatype));
- entry_offset = value;
- }
- else
- {
- memcpy(&entry_offset, buf_to_write,
- count * TIFFDataWidth(datatype));
- }
- }
- _TIFFfreeExt(tif, buf_to_write);
- buf_to_write = 0;
- /* -------------------------------------------------------------------- */
- /* Adjust the directory entry. */
- /* -------------------------------------------------------------------- */
- entry_type = datatype;
- entry_count = (uint64_t)count;
- memcpy(direntry_raw + 2, &entry_type, sizeof(uint16_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabShort((uint16_t *)(direntry_raw + 2));
- if (!(tif->tif_flags & TIFF_BIGTIFF))
- {
- uint32_t value;
- value = (uint32_t)entry_count;
- memcpy(direntry_raw + 4, &value, sizeof(uint32_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)(direntry_raw + 4));
- value = (uint32_t)entry_offset;
- memcpy(direntry_raw + 8, &value, sizeof(uint32_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong((uint32_t *)(direntry_raw + 8));
- }
- else
- {
- memcpy(direntry_raw + 4, &entry_count, sizeof(uint64_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)(direntry_raw + 4));
- memcpy(direntry_raw + 12, &entry_offset, sizeof(uint64_t));
- if (tif->tif_flags & TIFF_SWAB)
- TIFFSwabLong8((uint64_t *)(direntry_raw + 12));
- }
- /* -------------------------------------------------------------------- */
- /* Write the directory entry out to disk. */
- /* -------------------------------------------------------------------- */
- if (!SeekOK(tif, read_offset))
- {
- TIFFErrorExtR(tif, module, "%s: Seek error accessing TIFF directory",
- tif->tif_name);
- return 0;
- }
- if (!WriteOK(tif, direntry_raw, dirsize))
- {
- TIFFErrorExtR(tif, module, "%s: Can not write TIFF directory entry.",
- tif->tif_name);
- return 0;
- }
- return 1;
- }
|