Exif.pm 174 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688
  1. #------------------------------------------------------------------------------
  2. # File: Exif.pm
  3. #
  4. # Description: Read EXIF/TIFF meta information
  5. #
  6. # Revisions: 11/25/2003 - P. Harvey Created
  7. # 02/06/2004 - P. Harvey Moved processing functions from ExifTool
  8. # 03/19/2004 - P. Harvey Check PreviewImage for validity
  9. # 11/11/2004 - P. Harvey Split off maker notes into MakerNotes.pm
  10. # 12/13/2004 - P. Harvey Added AUTOLOAD to load write routines
  11. #
  12. # References: 0) http://www.exif.org/Exif2-2.PDF
  13. # 1) http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf
  14. # 2) http://www.adobe.com/products/dng/pdfs/dng_spec_1_3_0_0.pdf
  15. # 3) http://www.awaresystems.be/imaging/tiff/tifftags.html
  16. # 4) http://www.remotesensing.org/libtiff/TIFFTechNote2.html
  17. # 5) http://www.exif.org/dcf.PDF
  18. # 6) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html
  19. # 7) http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf
  20. # 8) http://www.ozhiker.com/electronics/pjmt/jpeg_info/meta.html
  21. # 9) http://hul.harvard.edu/jhove/tiff-tags.html
  22. # 10) http://partners.adobe.com/public/developer/en/tiff/TIFFPM6.pdf
  23. # 11) Robert Mucke private communication
  24. # 12) http://www.broomscloset.com/closet/photo/exif/TAG2000-22_DIS12234-2.PDF
  25. # 13) http://www.microsoft.com/whdc/xps/wmphoto.mspx
  26. # 14) http://www.asmail.be/msg0054681802.html
  27. # 15) http://crousseau.free.fr/imgfmt_raw.htm
  28. # 16) http://www.cybercom.net/~dcoffin/dcraw/
  29. # 17) http://www.digitalpreservation.gov/formats/content/tiff_tags.shtml
  30. # 18) http://www.asmail.be/msg0055568584.html
  31. # 19) http://libpsd.graphest.com/files/Photoshop%20File%20Formats.pdf
  32. # 20) http://tiki-lounge.com/~raf/tiff/fields.html
  33. # 21) http://community.roxen.com/developers/idocs/rfc/rfc3949.html
  34. # 22) http://tools.ietf.org/html/draft-ietf-fax-tiff-fx-extension1-01
  35. # 23) MetaMorph Stack (STK) Image File Format:
  36. # --> ftp://ftp.meta.moleculardevices.com/support/stack/STK.doc
  37. # 24) http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf (Exif 2.3)
  38. # 25) Vesa Kivisto private communication (7D)
  39. # 26) Jeremy Brown private communication
  40. # 27) Gregg Lee private communication
  41. # 28) http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/cinemadng/pdfs/CinemaDNG_Format_Specification_v1_1.pdf
  42. # 29) http://www.libtiff.org
  43. # JD) Jens Duttke private communication
  44. #------------------------------------------------------------------------------
  45. package Image::ExifTool::Exif;
  46. use strict;
  47. use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber %intFormat
  48. %lightSource %flash %compression %photometricInterpretation %orientation
  49. %subfileType);
  50. use Image::ExifTool qw(:DataAccess :Utils);
  51. use Image::ExifTool::MakerNotes;
  52. $VERSION = '3.77';
  53. sub ProcessExif($$$);
  54. sub WriteExif($$$);
  55. sub CheckExif($$$);
  56. sub RebuildMakerNotes($$$);
  57. sub EncodeExifText($$);
  58. sub ValidateIFD($;$);
  59. sub ProcessTiffIFD($$$);
  60. sub PrintParameter($$$);
  61. sub GetOffList($$$$$);
  62. sub PrintLensInfo($);
  63. sub ConvertLensInfo($);
  64. # size limit for loading binary data block into memory
  65. sub BINARY_DATA_LIMIT { return 10 * 1024 * 1024; }
  66. # byte sizes for the various EXIF format types below
  67. @formatSize = (undef,1,1,2,4,8,1,1,2,4,8,4,8,4,2,8,8,8,8);
  68. @formatName = (
  69. undef, 'int8u', 'string', 'int16u',
  70. 'int32u', 'rational64u','int8s', 'undef',
  71. 'int16s', 'int32s', 'rational64s','float',
  72. 'double', 'ifd', 'unicode', 'complex',
  73. 'int64u', 'int64s', 'ifd64', # (new BigTIFF formats)
  74. );
  75. # hash to look up EXIF format numbers by name
  76. # (format types are all lower case)
  77. %formatNumber = (
  78. 'int8u' => 1, # BYTE
  79. 'string' => 2, # ASCII
  80. 'int16u' => 3, # SHORT
  81. 'int32u' => 4, # LONG
  82. 'rational64u' => 5, # RATIONAL
  83. 'int8s' => 6, # SBYTE
  84. 'undef' => 7, # UNDEFINED
  85. 'binary' => 7, # (same as undef)
  86. 'int16s' => 8, # SSHORT
  87. 'int32s' => 9, # SLONG
  88. 'rational64s' => 10, # SRATIONAL
  89. 'float' => 11, # FLOAT
  90. 'double' => 12, # DOUBLE
  91. 'ifd' => 13, # IFD (with int32u format)
  92. 'unicode' => 14, # UNICODE [see Note below]
  93. 'complex' => 15, # COMPLEX [see Note below]
  94. 'int64u' => 16, # LONG8 [BigTIFF]
  95. 'int64s' => 17, # SLONG8 [BigTIFF]
  96. 'ifd64' => 18, # IFD8 (with int64u format) [BigTIFF]
  97. # Note: unicode and complex types are not yet properly supported by ExifTool.
  98. # These are types which have been observed in the Adobe DNG SDK code, but
  99. # aren't fully supported there either. We know the sizes, but that's about it.
  100. # We don't know if the unicode is null terminated, or the format for complex
  101. # (although I suspect it would be two 4-byte floats, real and imaginary).
  102. );
  103. # lookup for integer format strings
  104. %intFormat = (
  105. 'int8u' => 1,
  106. 'int16u' => 3,
  107. 'int32u' => 4,
  108. 'int8s' => 6,
  109. 'int16s' => 8,
  110. 'int32s' => 9,
  111. 'ifd' => 13,
  112. 'int64u' => 16,
  113. 'int64s' => 17,
  114. 'ifd64' => 18,
  115. );
  116. # EXIF LightSource PrintConv values
  117. %lightSource = (
  118. 0 => 'Unknown',
  119. 1 => 'Daylight',
  120. 2 => 'Fluorescent',
  121. 3 => 'Tungsten (Incandescent)',
  122. 4 => 'Flash',
  123. 9 => 'Fine Weather',
  124. 10 => 'Cloudy',
  125. 11 => 'Shade',
  126. 12 => 'Daylight Fluorescent', # (D 5700 - 7100K)
  127. 13 => 'Day White Fluorescent', # (N 4600 - 5500K)
  128. 14 => 'Cool White Fluorescent', # (W 3800 - 4500K)
  129. 15 => 'White Fluorescent', # (WW 3250 - 3800K)
  130. 16 => 'Warm White Fluorescent', # (L 2600 - 3250K)
  131. 17 => 'Standard Light A',
  132. 18 => 'Standard Light B',
  133. 19 => 'Standard Light C',
  134. 20 => 'D55',
  135. 21 => 'D65',
  136. 22 => 'D75',
  137. 23 => 'D50',
  138. 24 => 'ISO Studio Tungsten',
  139. 255 => 'Other',
  140. );
  141. # EXIF Flash values
  142. %flash = (
  143. OTHER => sub {
  144. # translate "Off" and "On" when writing
  145. my ($val, $inv) = @_;
  146. return undef unless $inv and $val =~ /^(off|on)$/i;
  147. return lc $val eq 'off' ? 0x00 : 0x01;
  148. },
  149. 0x00 => 'No Flash',
  150. 0x01 => 'Fired',
  151. 0x05 => 'Fired, Return not detected',
  152. 0x07 => 'Fired, Return detected',
  153. 0x08 => 'On, Did not fire', # not charged up?
  154. 0x09 => 'On, Fired',
  155. 0x0d => 'On, Return not detected',
  156. 0x0f => 'On, Return detected',
  157. 0x10 => 'Off, Did not fire',
  158. 0x14 => 'Off, Did not fire, Return not detected',
  159. 0x18 => 'Auto, Did not fire',
  160. 0x19 => 'Auto, Fired',
  161. 0x1d => 'Auto, Fired, Return not detected',
  162. 0x1f => 'Auto, Fired, Return detected',
  163. 0x20 => 'No flash function',
  164. 0x30 => 'Off, No flash function',
  165. 0x41 => 'Fired, Red-eye reduction',
  166. 0x45 => 'Fired, Red-eye reduction, Return not detected',
  167. 0x47 => 'Fired, Red-eye reduction, Return detected',
  168. 0x49 => 'On, Red-eye reduction',
  169. 0x4d => 'On, Red-eye reduction, Return not detected',
  170. 0x4f => 'On, Red-eye reduction, Return detected',
  171. 0x50 => 'Off, Red-eye reduction',
  172. 0x58 => 'Auto, Did not fire, Red-eye reduction',
  173. 0x59 => 'Auto, Fired, Red-eye reduction',
  174. 0x5d => 'Auto, Fired, Red-eye reduction, Return not detected',
  175. 0x5f => 'Auto, Fired, Red-eye reduction, Return detected',
  176. );
  177. # TIFF Compression values
  178. # (values with format "Xxxxx XXX Compressed" are used to identify RAW file types)
  179. %compression = (
  180. 1 => 'Uncompressed',
  181. 2 => 'CCITT 1D',
  182. 3 => 'T4/Group 3 Fax',
  183. 4 => 'T6/Group 4 Fax',
  184. 5 => 'LZW',
  185. 6 => 'JPEG (old-style)', #3
  186. 7 => 'JPEG', #4
  187. 8 => 'Adobe Deflate', #3
  188. 9 => 'JBIG B&W', #3
  189. 10 => 'JBIG Color', #3
  190. 99 => 'JPEG', #16
  191. 262 => 'Kodak 262', #16
  192. 32766 => 'Next', #3
  193. 32767 => 'Sony ARW Compressed', #16
  194. 32769 => 'Packed RAW', #PH (used by Epson, Nikon, Samsung)
  195. 32770 => 'Samsung SRW Compressed', #PH
  196. 32771 => 'CCIRLEW', #3
  197. 32772 => 'Samsung SRW Compressed 2', #PH (NX3000,NXmini)
  198. 32773 => 'PackBits',
  199. 32809 => 'Thunderscan', #3
  200. 32867 => 'Kodak KDC Compressed', #PH
  201. 32895 => 'IT8CTPAD', #3
  202. 32896 => 'IT8LW', #3
  203. 32897 => 'IT8MP', #3
  204. 32898 => 'IT8BL', #3
  205. 32908 => 'PixarFilm', #3
  206. 32909 => 'PixarLog', #3
  207. 32946 => 'Deflate', #3
  208. 32947 => 'DCS', #3
  209. 34661 => 'JBIG', #3
  210. 34676 => 'SGILog', #3
  211. 34677 => 'SGILog24', #3
  212. 34712 => 'JPEG 2000', #3
  213. 34713 => 'Nikon NEF Compressed', #PH
  214. 34715 => 'JBIG2 TIFF FX', #20
  215. 34718 => 'Microsoft Document Imaging (MDI) Binary Level Codec', #18
  216. 34719 => 'Microsoft Document Imaging (MDI) Progressive Transform Codec', #18
  217. 34720 => 'Microsoft Document Imaging (MDI) Vector', #18
  218. 34892 => 'Lossy JPEG', # (DNG 1.4)
  219. 65000 => 'Kodak DCR Compressed', #PH
  220. 65535 => 'Pentax PEF Compressed', #Jens
  221. );
  222. %photometricInterpretation = (
  223. 0 => 'WhiteIsZero',
  224. 1 => 'BlackIsZero',
  225. 2 => 'RGB',
  226. 3 => 'RGB Palette',
  227. 4 => 'Transparency Mask',
  228. 5 => 'CMYK',
  229. 6 => 'YCbCr',
  230. 8 => 'CIELab',
  231. 9 => 'ICCLab', #3
  232. 10 => 'ITULab', #3
  233. 32803 => 'Color Filter Array', #2
  234. 32844 => 'Pixar LogL', #3
  235. 32845 => 'Pixar LogLuv', #3
  236. 34892 => 'Linear Raw', #2
  237. );
  238. %orientation = (
  239. 1 => 'Horizontal (normal)',
  240. 2 => 'Mirror horizontal',
  241. 3 => 'Rotate 180',
  242. 4 => 'Mirror vertical',
  243. 5 => 'Mirror horizontal and rotate 270 CW',
  244. 6 => 'Rotate 90 CW',
  245. 7 => 'Mirror horizontal and rotate 90 CW',
  246. 8 => 'Rotate 270 CW',
  247. );
  248. %subfileType = (
  249. 0 => 'Full-resolution Image',
  250. 1 => 'Reduced-resolution image',
  251. 2 => 'Single page of multi-page image',
  252. 3 => 'Single page of multi-page reduced-resolution image',
  253. 4 => 'Transparency mask',
  254. 5 => 'Transparency mask of reduced-resolution image',
  255. 6 => 'Transparency mask of multi-page image',
  256. 7 => 'Transparency mask of reduced-resolution multi-page image',
  257. 0x10001 => 'Alternate reduced-resolution image', # (DNG 1.2)
  258. 0xffffffff => 'invalid', #(found in E5700 NEF's)
  259. BITMASK => {
  260. 0 => 'Reduced resolution',
  261. 1 => 'Single page',
  262. 2 => 'Transparency mask',
  263. 3 => 'TIFF/IT final page', #20
  264. 4 => 'TIFF-FX mixed raster content', #20
  265. },
  266. );
  267. # PrintConv for parameter tags
  268. %Image::ExifTool::Exif::printParameter = (
  269. PrintConv => {
  270. 0 => 'Normal',
  271. OTHER => \&Image::ExifTool::Exif::PrintParameter,
  272. },
  273. );
  274. # ValueConv that makes long values binary type
  275. my %longBin = (
  276. ValueConv => 'length($val) > 64 ? \$val : $val',
  277. ValueConvInv => '$val',
  278. );
  279. # PrintConv for SampleFormat (0x153)
  280. my %sampleFormat = (
  281. 1 => 'Unsigned', # unsigned integer
  282. 2 => 'Signed', # two's complement signed integer
  283. 3 => 'Float', # IEEE floating point
  284. 4 => 'Undefined',
  285. 5 => 'Complex int', # complex integer (ref 3)
  286. 6 => 'Complex float', # complex IEEE floating point (ref 3)
  287. );
  288. # main EXIF tag table
  289. %Image::ExifTool::Exif::Main = (
  290. GROUPS => { 0 => 'EXIF', 1 => 'IFD0', 2 => 'Image'},
  291. WRITE_PROC => \&WriteExif,
  292. WRITE_GROUP => 'ExifIFD', # default write group
  293. SET_GROUP1 => 1, # set group1 name to directory name for all tags in table
  294. 0x1 => {
  295. Name => 'InteropIndex',
  296. Description => 'Interoperability Index',
  297. PrintConv => {
  298. R98 => 'R98 - DCF basic file (sRGB)',
  299. R03 => 'R03 - DCF option file (Adobe RGB)',
  300. THM => 'THM - DCF thumbnail file',
  301. },
  302. },
  303. 0x2 => { #5
  304. Name => 'InteropVersion',
  305. Description => 'Interoperability Version',
  306. RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators)
  307. },
  308. 0x0b => { #PH
  309. Name => 'ProcessingSoftware',
  310. Notes => 'used by ACD Systems Digital Imaging',
  311. },
  312. 0xfe => {
  313. Name => 'SubfileType',
  314. # set priority directory if this is the full resolution image
  315. DataMember => 'SubfileType',
  316. RawConv => '$self->SetPriorityDir() if $val eq "0"; $$self{SubfileType} = $val',
  317. PrintConv => \%subfileType,
  318. },
  319. 0xff => {
  320. Name => 'OldSubfileType',
  321. # set priority directory if this is the full resolution image
  322. RawConv => '$self->SetPriorityDir() if $val eq "1"; $val',
  323. PrintConv => {
  324. 1 => 'Full-resolution image',
  325. 2 => 'Reduced-resolution image',
  326. 3 => 'Single page of multi-page image',
  327. },
  328. },
  329. 0x100 => {
  330. Name => 'ImageWidth',
  331. # even though Group 1 is set dynamically we need to register IFD1 once
  332. # so it will show up in the group lists
  333. Groups => { 1 => 'IFD1' },
  334. # Note: priority 0 tags automatically have their priority increased for the
  335. # priority direcory (the directory with a SubfileType of "Full-resolution image")
  336. Priority => 0,
  337. },
  338. 0x101 => {
  339. Name => 'ImageHeight',
  340. Notes => 'called ImageLength by the EXIF spec.',
  341. Priority => 0,
  342. },
  343. 0x102 => {
  344. Name => 'BitsPerSample',
  345. Priority => 0,
  346. },
  347. 0x103 => {
  348. Name => 'Compression',
  349. DataMember => 'Compression',
  350. SeparateTable => 'Compression',
  351. RawConv => q{
  352. Image::ExifTool::Exif::IdentifyRawFile($self, $val);
  353. return $$self{Compression} = $val;
  354. },
  355. PrintConv => \%compression,
  356. Priority => 0,
  357. },
  358. 0x106 => {
  359. Name => 'PhotometricInterpretation',
  360. PrintConv => \%photometricInterpretation,
  361. Priority => 0,
  362. },
  363. 0x107 => {
  364. Name => 'Thresholding',
  365. PrintConv => {
  366. 1 => 'No dithering or halftoning',
  367. 2 => 'Ordered dither or halftone',
  368. 3 => 'Randomized dither',
  369. },
  370. },
  371. 0x108 => 'CellWidth',
  372. 0x109 => 'CellLength',
  373. 0x10a => {
  374. Name => 'FillOrder',
  375. PrintConv => {
  376. 1 => 'Normal',
  377. 2 => 'Reversed',
  378. },
  379. },
  380. 0x10d => 'DocumentName',
  381. 0x10e => {
  382. Name => 'ImageDescription',
  383. Priority => 0,
  384. },
  385. 0x10f => {
  386. Name => 'Make',
  387. Groups => { 2 => 'Camera' },
  388. DataMember => 'Make',
  389. # remove trailing blanks and save as an ExifTool member variable
  390. RawConv => '$val =~ s/\s+$//; $$self{Make} = $val',
  391. # NOTE: trailing "blanks" (spaces) are removed from all EXIF tags which
  392. # may be "unknown" (filled with spaces) according to the EXIF spec.
  393. # This allows conditional replacement with "exiftool -TAG-= -TAG=VALUE".
  394. # - also removed are any other trailing whitespace characters
  395. },
  396. 0x110 => {
  397. Name => 'Model',
  398. Description => 'Camera Model Name',
  399. Groups => { 2 => 'Camera' },
  400. DataMember => 'Model',
  401. # remove trailing blanks and save as an ExifTool member variable
  402. RawConv => '$val =~ s/\s+$//; $$self{Model} = $val',
  403. },
  404. 0x111 => [
  405. {
  406. Condition => q[
  407. $$self{TIFF_TYPE} eq 'MRW' and $$self{DIR_NAME} eq 'IFD0' and
  408. $$self{Model} =~ /^DiMAGE A200/
  409. ],
  410. Name => 'StripOffsets',
  411. IsOffset => 1,
  412. OffsetPair => 0x117, # point to associated byte counts
  413. # A200 stores this information in the wrong byte order!!
  414. ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
  415. ByteOrder => 'LittleEndian',
  416. },
  417. {
  418. Condition => q[
  419. ($$self{TIFF_TYPE} ne 'CR2' or $$self{DIR_NAME} ne 'IFD0') and
  420. ($$self{TIFF_TYPE} ne 'DNG' or $$self{DIR_NAME} !~ /^SubIFD[12]$/)
  421. ],
  422. Name => 'StripOffsets',
  423. IsOffset => 1,
  424. OffsetPair => 0x117, # point to associated byte counts
  425. ValueConv => 'length($val) > 32 ? \$val : $val',
  426. },
  427. {
  428. Condition => '$$self{DIR_NAME} eq "IFD0"',
  429. Name => 'PreviewImageStart',
  430. IsOffset => 1,
  431. OffsetPair => 0x117,
  432. Notes => q{
  433. PreviewImageStart in IFD0 of CR2 images and SubIFD1 of DNG images, and
  434. JpgFromRawStart in SubIFD2 of DNG images
  435. },
  436. DataTag => 'PreviewImage',
  437. Writable => 'int32u',
  438. WriteGroup => 'IFD0',
  439. WriteCondition => '$$self{TIFF_TYPE} eq "CR2"',
  440. Protected => 2,
  441. },
  442. {
  443. Condition => '$$self{DIR_NAME} eq "SubIFD1"',
  444. Name => 'PreviewImageStart',
  445. IsOffset => 1,
  446. OffsetPair => 0x117,
  447. DataTag => 'PreviewImage',
  448. Writable => 'int32u',
  449. WriteGroup => 'SubIFD1',
  450. WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
  451. Protected => 2,
  452. },
  453. {
  454. Name => 'JpgFromRawStart',
  455. IsOffset => 1,
  456. OffsetPair => 0x117,
  457. DataTag => 'JpgFromRaw',
  458. Writable => 'int32u',
  459. WriteGroup => 'SubIFD2',
  460. WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
  461. Protected => 2,
  462. },
  463. ],
  464. 0x112 => {
  465. Name => 'Orientation',
  466. PrintConv => \%orientation,
  467. Priority => 0, # so PRIORITY_DIR takes precedence
  468. },
  469. 0x115 => {
  470. Name => 'SamplesPerPixel',
  471. Priority => 0,
  472. },
  473. 0x116 => {
  474. Name => 'RowsPerStrip',
  475. Priority => 0,
  476. },
  477. 0x117 => [
  478. {
  479. Condition => q[
  480. $$self{TIFF_TYPE} eq 'MRW' and $$self{DIR_NAME} eq 'IFD0' and
  481. $$self{Model} =~ /^DiMAGE A200/
  482. ],
  483. Name => 'StripByteCounts',
  484. OffsetPair => 0x111, # point to associated offset
  485. # A200 stores this information in the wrong byte order!!
  486. ValueConv => '$val=join(" ",unpack("N*",pack("V*",split(" ",$val))));\$val',
  487. ByteOrder => 'LittleEndian',
  488. },
  489. {
  490. Condition => q[
  491. ($$self{TIFF_TYPE} ne 'CR2' or $$self{DIR_NAME} ne 'IFD0') and
  492. ($$self{TIFF_TYPE} ne 'DNG' or $$self{DIR_NAME} !~ /^SubIFD[12]$/)
  493. ],
  494. Name => 'StripByteCounts',
  495. OffsetPair => 0x111, # point to associated offset
  496. ValueConv => 'length($val) > 32 ? \$val : $val',
  497. },
  498. {
  499. Condition => '$$self{DIR_NAME} eq "IFD0"',
  500. Name => 'PreviewImageLength',
  501. OffsetPair => 0x111,
  502. Notes => q{
  503. PreviewImageLength in IFD0 of CR2 images and SubIFD1 of DNG images, and
  504. JpgFromRawLength in SubIFD2 of DNG images
  505. },
  506. DataTag => 'PreviewImage',
  507. Writable => 'int32u',
  508. WriteGroup => 'IFD0',
  509. WriteCondition => '$$self{TIFF_TYPE} eq "CR2"',
  510. Protected => 2,
  511. },
  512. {
  513. Condition => '$$self{DIR_NAME} eq "SubIFD1"',
  514. Name => 'PreviewImageLength',
  515. OffsetPair => 0x111,
  516. DataTag => 'PreviewImage',
  517. Writable => 'int32u',
  518. WriteGroup => 'SubIFD1',
  519. WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
  520. Protected => 2,
  521. },
  522. {
  523. Name => 'JpgFromRawLength',
  524. OffsetPair => 0x111,
  525. DataTag => 'JpgFromRaw',
  526. Writable => 'int32u',
  527. WriteGroup => 'SubIFD2',
  528. WriteCondition => '$$self{TIFF_TYPE} eq "DNG"',
  529. Protected => 2,
  530. },
  531. ],
  532. 0x118 => 'MinSampleValue',
  533. 0x119 => 'MaxSampleValue',
  534. 0x11a => {
  535. Name => 'XResolution',
  536. Priority => 0, # so PRIORITY_DIR takes precedence
  537. },
  538. 0x11b => {
  539. Name => 'YResolution',
  540. Priority => 0,
  541. },
  542. 0x11c => {
  543. Name => 'PlanarConfiguration',
  544. PrintConv => {
  545. 1 => 'Chunky',
  546. 2 => 'Planar',
  547. },
  548. Priority => 0,
  549. },
  550. 0x11d => 'PageName',
  551. 0x11e => 'XPosition',
  552. 0x11f => 'YPosition',
  553. # FreeOffsets/FreeByteCounts are used by Ricoh for RMETA information
  554. # in TIFF images (not yet supported)
  555. 0x120 => {
  556. Name => 'FreeOffsets',
  557. IsOffset => 1,
  558. OffsetPair => 0x121,
  559. ValueConv => 'length($val) > 32 ? \$val : $val',
  560. },
  561. 0x121 => {
  562. Name => 'FreeByteCounts',
  563. OffsetPair => 0x120,
  564. ValueConv => 'length($val) > 32 ? \$val : $val',
  565. },
  566. 0x122 => {
  567. Name => 'GrayResponseUnit',
  568. PrintConv => { #3
  569. 1 => 0.1,
  570. 2 => 0.001,
  571. 3 => 0.0001,
  572. 4 => 0.00001,
  573. 5 => 0.000001,
  574. },
  575. },
  576. 0x123 => {
  577. Name => 'GrayResponseCurve',
  578. Binary => 1,
  579. },
  580. 0x124 => {
  581. Name => 'T4Options',
  582. PrintConv => { BITMASK => {
  583. 0 => '2-Dimensional encoding',
  584. 1 => 'Uncompressed',
  585. 2 => 'Fill bits added',
  586. } }, #3
  587. },
  588. 0x125 => {
  589. Name => 'T6Options',
  590. PrintConv => { BITMASK => {
  591. 1 => 'Uncompressed',
  592. } }, #3
  593. },
  594. 0x128 => {
  595. Name => 'ResolutionUnit',
  596. Notes => 'the value 1 is not standard EXIF',
  597. PrintConv => {
  598. 1 => 'None',
  599. 2 => 'inches',
  600. 3 => 'cm',
  601. },
  602. Priority => 0,
  603. },
  604. 0x129 => 'PageNumber',
  605. 0x12c => 'ColorResponseUnit', #9
  606. 0x12d => {
  607. Name => 'TransferFunction',
  608. Binary => 1,
  609. },
  610. 0x131 => {
  611. Name => 'Software',
  612. RawConv => '$val =~ s/\s+$//; $val', # trim trailing blanks
  613. },
  614. 0x132 => {
  615. Name => 'ModifyDate',
  616. Groups => { 2 => 'Time' },
  617. Notes => 'called DateTime by the EXIF spec.',
  618. PrintConv => '$self->ConvertDateTime($val)',
  619. },
  620. 0x13b => {
  621. Name => 'Artist',
  622. Groups => { 2 => 'Author' },
  623. Notes => 'becomes a list-type tag when the MWG module is loaded',
  624. RawConv => '$val =~ s/\s+$//; $val', # trim trailing blanks
  625. },
  626. 0x13c => 'HostComputer',
  627. 0x13d => {
  628. Name => 'Predictor',
  629. PrintConv => {
  630. 1 => 'None',
  631. 2 => 'Horizontal differencing',
  632. },
  633. },
  634. 0x13e => {
  635. Name => 'WhitePoint',
  636. Groups => { 2 => 'Camera' },
  637. },
  638. 0x13f => {
  639. Name => 'PrimaryChromaticities',
  640. Priority => 0,
  641. },
  642. 0x140 => {
  643. Name => 'ColorMap',
  644. Format => 'binary',
  645. Binary => 1,
  646. },
  647. 0x141 => 'HalftoneHints',
  648. 0x142 => 'TileWidth',
  649. 0x143 => 'TileLength',
  650. 0x144 => {
  651. Name => 'TileOffsets',
  652. IsOffset => 1,
  653. OffsetPair => 0x145,
  654. ValueConv => 'length($val) > 32 ? \$val : $val',
  655. },
  656. 0x145 => {
  657. Name => 'TileByteCounts',
  658. OffsetPair => 0x144,
  659. ValueConv => 'length($val) > 32 ? \$val : $val',
  660. },
  661. 0x146 => 'BadFaxLines', #3
  662. 0x147 => { #3
  663. Name => 'CleanFaxData',
  664. PrintConv => {
  665. 0 => 'Clean',
  666. 1 => 'Regenerated',
  667. 2 => 'Unclean',
  668. },
  669. },
  670. 0x148 => 'ConsecutiveBadFaxLines', #3
  671. 0x14a => [
  672. {
  673. Name => 'SubIFD',
  674. # use this opportunity to identify an ARW image, and if so we
  675. # must decide if this is a SubIFD or the A100 raw data
  676. # (use SubfileType, Compression and FILE_TYPE to identify ARW/SR2,
  677. # then call SetARW to finish the job)
  678. Condition => q{
  679. $$self{DIR_NAME} ne 'IFD0' or $$self{FILE_TYPE} ne 'TIFF' or
  680. $$self{Make} !~ /^SONY/ or
  681. not $$self{SubfileType} or $$self{SubfileType} != 1 or
  682. not $$self{Compression} or $$self{Compression} != 6 or
  683. not require Image::ExifTool::Sony or
  684. Image::ExifTool::Sony::SetARW($self, $valPt)
  685. },
  686. Groups => { 1 => 'SubIFD' },
  687. Flags => 'SubIFD',
  688. SubDirectory => {
  689. Start => '$val',
  690. MaxSubdirs => 10, # (have seen 5 in a DNG 1.4 image)
  691. },
  692. },
  693. { #16
  694. Name => 'A100DataOffset',
  695. Notes => 'the data offset in original Sony DSLR-A100 ARW images',
  696. DataMember => 'A100DataOffset',
  697. RawConv => '$$self{A100DataOffset} = $val',
  698. IsOffset => 1,
  699. Protected => 2,
  700. },
  701. ],
  702. 0x14c => {
  703. Name => 'InkSet',
  704. PrintConv => { #3
  705. 1 => 'CMYK',
  706. 2 => 'Not CMYK',
  707. },
  708. },
  709. 0x14d => 'InkNames', #3
  710. 0x14e => 'NumberofInks', #3
  711. 0x150 => 'DotRange',
  712. 0x151 => 'TargetPrinter',
  713. 0x152 => {
  714. Name => 'ExtraSamples',
  715. PrintConv => { #20
  716. 0 => 'Unspecified',
  717. 1 => 'Associated Alpha',
  718. 2 => 'Unassociated Alpha',
  719. },
  720. },
  721. 0x153 => {
  722. Name => 'SampleFormat',
  723. Notes => 'SamplesPerPixel values',
  724. PrintConvColumns => 2,
  725. PrintConv => [ \%sampleFormat, \%sampleFormat, \%sampleFormat, \%sampleFormat ],
  726. },
  727. 0x154 => 'SMinSampleValue',
  728. 0x155 => 'SMaxSampleValue',
  729. 0x156 => 'TransferRange',
  730. 0x157 => 'ClipPath', #3
  731. 0x158 => 'XClipPathUnits', #3
  732. 0x159 => 'YClipPathUnits', #3
  733. 0x15a => { #3
  734. Name => 'Indexed',
  735. PrintConv => { 0 => 'Not indexed', 1 => 'Indexed' },
  736. },
  737. 0x15b => {
  738. Name => 'JPEGTables',
  739. Binary => 1,
  740. },
  741. 0x15f => { #10
  742. Name => 'OPIProxy',
  743. PrintConv => {
  744. 0 => 'Higher resolution image does not exist',
  745. 1 => 'Higher resolution image exists',
  746. },
  747. },
  748. # 0x181 => 'Decode', #20 (typo! - should be 0x1b1, ref 21)
  749. # 0x182 => 'DefaultImageColor', #20 (typo! - should be 0x1b2, ref 21)
  750. 0x190 => { #3
  751. Name => 'GlobalParametersIFD',
  752. Groups => { 1 => 'GlobParamIFD' },
  753. Flags => 'SubIFD',
  754. SubDirectory => {
  755. DirName => 'GlobParamIFD',
  756. Start => '$val',
  757. MaxSubdirs => 1,
  758. },
  759. },
  760. 0x191 => { #3
  761. Name => 'ProfileType',
  762. PrintConv => { 0 => 'Unspecified', 1 => 'Group 3 FAX' },
  763. },
  764. 0x192 => { #3
  765. Name => 'FaxProfile',
  766. PrintConv => {
  767. 0 => 'Unknown',
  768. 1 => 'Minimal B&W lossless, S',
  769. 2 => 'Extended B&W lossless, F',
  770. 3 => 'Lossless JBIG B&W, J',
  771. 4 => 'Lossy color and grayscale, C',
  772. 5 => 'Lossless color and grayscale, L',
  773. 6 => 'Mixed raster content, M',
  774. 7 => 'Profile T', #20
  775. 255 => 'Multi Profiles', #20
  776. },
  777. },
  778. 0x193 => { #3
  779. Name => 'CodingMethods',
  780. PrintConv => { BITMASK => {
  781. 0 => 'Unspecified compression',
  782. 1 => 'Modified Huffman',
  783. 2 => 'Modified Read',
  784. 3 => 'Modified MR',
  785. 4 => 'JBIG',
  786. 5 => 'Baseline JPEG',
  787. 6 => 'JBIG color',
  788. } },
  789. },
  790. 0x194 => 'VersionYear', #3
  791. 0x195 => 'ModeNumber', #3
  792. 0x1b1 => 'Decode', #3
  793. 0x1b2 => 'DefaultImageColor', #3 (changed to ImageBaseColor, ref 21)
  794. 0x1b3 => 'T82Options', #20
  795. 0x1b5 => { #19
  796. Name => 'JPEGTables',
  797. Binary => 1,
  798. },
  799. 0x200 => {
  800. Name => 'JPEGProc',
  801. PrintConv => {
  802. 1 => 'Baseline',
  803. 14 => 'Lossless',
  804. },
  805. },
  806. 0x201 => [
  807. {
  808. Name => 'ThumbnailOffset',
  809. Notes => q{
  810. ThumbnailOffset in IFD1 of JPEG and some TIFF-based images, IFD0 of MRW
  811. images and AVI and MOV videos, and the SubIFD in IFD1 of SRW images;
  812. PreviewImageStart in MakerNotes and IFD0 of ARW and SR2 images;
  813. JpgFromRawStart in SubIFD of NEF images and IFD2 of PEF images; and
  814. OtherImageStart in everything else
  815. },
  816. # thumbnail is found in IFD1 of JPEG and TIFF images, and
  817. # IFD0 of EXIF information in FujiFilm AVI (RIFF) and MOV videos
  818. Condition => q{
  819. $$self{DIR_NAME} eq 'IFD1' or
  820. ($$self{DIR_NAME} eq 'IFD0' and $$self{FILE_TYPE} =~ /^(RIFF|MOV)$/)
  821. },
  822. IsOffset => 1,
  823. OffsetPair => 0x202,
  824. DataTag => 'ThumbnailImage',
  825. Writable => 'int32u',
  826. WriteGroup => 'IFD1',
  827. # according to the EXIF spec. a JPEG-compressed thumbnail image may not
  828. # be stored in a TIFF file, but these TIFF-based RAW image formats
  829. # use IFD1 for a JPEG-compressed thumbnail: CR2, ARW, SR2 and PEF.
  830. # (SRF also stores a JPEG image in IFD1, but it is actually a preview
  831. # and we don't yet write SRF anyway)
  832. WriteCondition => q{
  833. $$self{FILE_TYPE} ne "TIFF" or
  834. $$self{TIFF_TYPE} =~ /^(CR2|ARW|SR2|PEF)$/
  835. },
  836. Protected => 2,
  837. },
  838. {
  839. Name => 'ThumbnailOffset',
  840. # thumbnail in IFD0 of MRW images (Minolta A200)
  841. # and IFD0 of NRW images (Nikon Coolpix P6000,P7000,P7100)
  842. Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(MRW|NRW)$/',
  843. IsOffset => 1,
  844. OffsetPair => 0x202,
  845. # A200 uses the wrong base offset for this pointer!!
  846. WrongBase => '$$self{Model} =~ /^DiMAGE A200/ ? $$self{MRW_WrongBase} : undef',
  847. DataTag => 'ThumbnailImage',
  848. Writable => 'int32u',
  849. WriteGroup => 'IFD0',
  850. WriteCondition => '$$self{FILE_TYPE} =~ /^(MRW|NRW)$/',
  851. Protected => 2,
  852. },
  853. {
  854. Name => 'ThumbnailOffset',
  855. # in SubIFD of IFD1 in Samsung SRW images
  856. Condition => q{
  857. $$self{TIFF_TYPE} eq 'SRW' and $$self{DIR_NAME} eq 'SubIFD' and
  858. $$self{PATH}[-2] eq 'IFD1'
  859. },
  860. IsOffset => 1,
  861. OffsetPair => 0x202,
  862. DataTag => 'ThumbnailImage',
  863. Writable => 'int32u',
  864. WriteGroup => 'SubIFD',
  865. WriteCondition => '$$self{TIFF_TYPE} eq "SRW"',
  866. Protected => 2,
  867. },
  868. {
  869. Name => 'PreviewImageStart',
  870. Condition => '$$self{DIR_NAME} eq "MakerNotes"',
  871. IsOffset => 1,
  872. OffsetPair => 0x202,
  873. DataTag => 'PreviewImage',
  874. Writable => 'int32u',
  875. WriteGroup => 'MakerNotes',
  876. # (no WriteCondition necessary because MakerNotes won't be created)
  877. Protected => 2,
  878. },
  879. {
  880. Name => 'PreviewImageStart',
  881. # PreviewImage in IFD0 of ARW and SR2 files for all models
  882. Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
  883. IsOffset => 1,
  884. OffsetPair => 0x202,
  885. DataTag => 'PreviewImage',
  886. Writable => 'int32u',
  887. WriteGroup => 'IFD0',
  888. WriteCondition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
  889. Protected => 2,
  890. },
  891. {
  892. Name => 'JpgFromRawStart',
  893. Condition => '$$self{DIR_NAME} eq "SubIFD"',
  894. IsOffset => 1,
  895. OffsetPair => 0x202,
  896. DataTag => 'JpgFromRaw',
  897. Writable => 'int32u',
  898. WriteGroup => 'SubIFD',
  899. # JpgFromRaw is in SubIFD of NEF, NRW and SRW files
  900. WriteCondition => '$$self{TIFF_TYPE} =~ /^(NEF|NRW|SRW)$/',
  901. Protected => 2,
  902. },
  903. {
  904. Name => 'JpgFromRawStart',
  905. Condition => '$$self{DIR_NAME} eq "IFD2"',
  906. IsOffset => 1,
  907. OffsetPair => 0x202,
  908. DataTag => 'JpgFromRaw',
  909. Writable => 'int32u',
  910. WriteGroup => 'IFD2',
  911. # JpgFromRaw is in IFD2 of PEF files
  912. WriteCondition => '$$self{TIFF_TYPE} eq "PEF"',
  913. Protected => 2,
  914. },
  915. {
  916. Name => 'OtherImageStart',
  917. Condition => '$$self{DIR_NAME} eq "SubIFD1"',
  918. IsOffset => 1,
  919. OffsetPair => 0x202,
  920. DataTag => 'OtherImage',
  921. Writable => 'int32u',
  922. WriteGroup => 'SubIFD1',
  923. Protected => 2,
  924. Permanent => 1, # (don't add/delete this tag: makes WriteCondition unnecessary)
  925. },
  926. {
  927. Name => 'OtherImageStart',
  928. Condition => '$$self{DIR_NAME} eq "SubIFD2"',
  929. IsOffset => 1,
  930. OffsetPair => 0x202,
  931. DataTag => 'OtherImage',
  932. Writable => 'int32u',
  933. WriteGroup => 'SubIFD2',
  934. Protected => 2,
  935. Permanent => 1, # (don't add/delete this tag: makes WriteCondition unnecessary)
  936. },
  937. {
  938. Name => 'OtherImageStart',
  939. IsOffset => 1,
  940. OffsetPair => 0x202,
  941. },
  942. ],
  943. 0x202 => [
  944. {
  945. Name => 'ThumbnailLength',
  946. Notes => q{
  947. ThumbnailLength in IFD1 of JPEG and some TIFF-based images, IFD0 of MRW
  948. images and AVI and MOV videos, and the SubIFD in IFD1 of SRW images;
  949. PreviewImageLength in MakerNotes and IFD0 of ARW and SR2 images;
  950. JpgFromRawLength in SubIFD of NEF images, and IFD2 of PEF images; and
  951. OtherImageLength in everything else
  952. },
  953. Condition => q{
  954. $$self{DIR_NAME} eq 'IFD1' or
  955. ($$self{DIR_NAME} eq 'IFD0' and $$self{FILE_TYPE} =~ /^(RIFF|MOV)$/)
  956. },
  957. OffsetPair => 0x201,
  958. DataTag => 'ThumbnailImage',
  959. Writable => 'int32u',
  960. WriteGroup => 'IFD1',
  961. WriteCondition => q{
  962. $$self{FILE_TYPE} ne "TIFF" or
  963. $$self{TIFF_TYPE} =~ /^(CR2|ARW|SR2|PEF)$/
  964. },
  965. Protected => 2,
  966. },
  967. {
  968. Name => 'ThumbnailLength',
  969. # thumbnail in IFD0 of MRW images (Minolta A200)
  970. # and IFD0 of NRW images (Nikon Coolpix P6000,P7000,P7100)
  971. Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(MRW|NRW)$/',
  972. OffsetPair => 0x201,
  973. DataTag => 'ThumbnailImage',
  974. Writable => 'int32u',
  975. WriteGroup => 'IFD0',
  976. WriteCondition => '$$self{FILE_TYPE} =~ /^(MRW|NRW)$/',
  977. Protected => 2,
  978. },
  979. {
  980. Name => 'ThumbnailLength',
  981. # in SubIFD of IFD1 in Samsung SRW images
  982. Condition => q{
  983. $$self{TIFF_TYPE} eq 'SRW' and $$self{DIR_NAME} eq 'SubIFD' and
  984. $$self{PATH}[-2] eq 'IFD1'
  985. },
  986. OffsetPair => 0x201,
  987. DataTag => 'ThumbnailImage',
  988. Writable => 'int32u',
  989. WriteGroup => 'SubIFD',
  990. WriteCondition => '$$self{TIFF_TYPE} eq "SRW"',
  991. Protected => 2,
  992. },
  993. {
  994. Name => 'PreviewImageLength',
  995. Condition => '$$self{DIR_NAME} eq "MakerNotes"',
  996. OffsetPair => 0x201,
  997. DataTag => 'PreviewImage',
  998. Writable => 'int32u',
  999. WriteGroup => 'MakerNotes',
  1000. # (no WriteCondition necessary because MakerNotes won't be created)
  1001. Protected => 2,
  1002. },
  1003. {
  1004. Name => 'PreviewImageLength',
  1005. # PreviewImage in IFD0 of ARW and SR2 files for all models
  1006. Condition => '$$self{DIR_NAME} eq "IFD0" and $$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
  1007. OffsetPair => 0x201,
  1008. DataTag => 'PreviewImage',
  1009. Writable => 'int32u',
  1010. WriteGroup => 'IFD0',
  1011. WriteCondition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
  1012. Protected => 2,
  1013. },
  1014. {
  1015. Name => 'JpgFromRawLength',
  1016. Condition => '$$self{DIR_NAME} eq "SubIFD"',
  1017. OffsetPair => 0x201,
  1018. DataTag => 'JpgFromRaw',
  1019. Writable => 'int32u',
  1020. WriteGroup => 'SubIFD',
  1021. WriteCondition => '$$self{TIFF_TYPE} =~ /^(NEF|NRW|SRW)$/',
  1022. Protected => 2,
  1023. },
  1024. {
  1025. Name => 'JpgFromRawLength',
  1026. Condition => '$$self{DIR_NAME} eq "IFD2"',
  1027. OffsetPair => 0x201,
  1028. DataTag => 'JpgFromRaw',
  1029. Writable => 'int32u',
  1030. WriteGroup => 'IFD2',
  1031. WriteCondition => '$$self{TIFF_TYPE} eq "PEF"',
  1032. Protected => 2,
  1033. },
  1034. {
  1035. Name => 'OtherImageLength',
  1036. Condition => '$$self{DIR_NAME} eq "SubIFD1"',
  1037. OffsetPair => 0x201,
  1038. DataTag => 'OtherImage',
  1039. Writable => 'int32u',
  1040. WriteGroup => 'SubIFD1',
  1041. Protected => 2,
  1042. Permanent => 1, # (don't add/delete this tag: makes WriteCondition unnecessary)
  1043. },
  1044. {
  1045. Name => 'OtherImageLength',
  1046. Condition => '$$self{DIR_NAME} eq "SubIFD2"',
  1047. OffsetPair => 0x201,
  1048. DataTag => 'OtherImage',
  1049. Writable => 'int32u',
  1050. WriteGroup => 'SubIFD2',
  1051. Protected => 2,
  1052. Permanent => 1, # (don't add/delete this tag: makes WriteCondition unnecessary)
  1053. },
  1054. {
  1055. Name => 'OtherImageLength',
  1056. OffsetPair => 0x201,
  1057. },
  1058. ],
  1059. 0x203 => 'JPEGRestartInterval',
  1060. 0x205 => 'JPEGLosslessPredictors',
  1061. 0x206 => 'JPEGPointTransforms',
  1062. 0x207 => {
  1063. Name => 'JPEGQTables',
  1064. IsOffset => 1,
  1065. # this tag is not supported for writing, so define an
  1066. # invalid offset pair to cause a "No size tag" error to be
  1067. # generated if we try to write a file containing this tag
  1068. OffsetPair => -1,
  1069. },
  1070. 0x208 => {
  1071. Name => 'JPEGDCTables',
  1072. IsOffset => 1,
  1073. OffsetPair => -1, # (see comment for JPEGQTables)
  1074. },
  1075. 0x209 => {
  1076. Name => 'JPEGACTables',
  1077. IsOffset => 1,
  1078. OffsetPair => -1, # (see comment for JPEGQTables)
  1079. },
  1080. 0x211 => {
  1081. Name => 'YCbCrCoefficients',
  1082. Priority => 0,
  1083. },
  1084. 0x212 => {
  1085. Name => 'YCbCrSubSampling',
  1086. PrintConvColumns => 2,
  1087. PrintConv => \%Image::ExifTool::JPEG::yCbCrSubSampling,
  1088. Priority => 0,
  1089. },
  1090. 0x213 => {
  1091. Name => 'YCbCrPositioning',
  1092. PrintConv => {
  1093. 1 => 'Centered',
  1094. 2 => 'Co-sited',
  1095. },
  1096. Priority => 0,
  1097. },
  1098. 0x214 => {
  1099. Name => 'ReferenceBlackWhite',
  1100. Priority => 0,
  1101. },
  1102. 0x22f => 'StripRowCounts',
  1103. 0x2bc => {
  1104. Name => 'ApplicationNotes', # (writable directory!)
  1105. Writable => 'int8u',
  1106. Format => 'undef',
  1107. Flags => [ 'Binary', 'Protected' ],
  1108. # this could be an XMP block
  1109. SubDirectory => {
  1110. DirName => 'XMP',
  1111. TagTable => 'Image::ExifTool::XMP::Main',
  1112. },
  1113. },
  1114. 0x3e7 => 'USPTOMiscellaneous', #20
  1115. 0x1000 => 'RelatedImageFileFormat', #5
  1116. 0x1001 => 'RelatedImageWidth', #5
  1117. 0x1002 => { #5
  1118. Name => 'RelatedImageHeight',
  1119. Notes => 'called RelatedImageLength by the DCF spec.',
  1120. },
  1121. # (0x474x tags written by MicrosoftPhoto)
  1122. 0x4746 => 'Rating', #PH
  1123. 0x4747 => { # (written by Digital Image Pro)
  1124. Name => 'XP_DIP_XML',
  1125. Format => 'undef',
  1126. # the following reference indicates this is Unicode:
  1127. # http://social.msdn.microsoft.com/Forums/en-US/isvvba/thread/ce6edcbb-8fc2-40c6-ad98-85f5d835ddfb
  1128. ValueConv => '$self->Decode($val,"UCS2","II")',
  1129. },
  1130. 0x4748 => {
  1131. Name => 'StitchInfo',
  1132. SubDirectory => {
  1133. TagTable => 'Image::ExifTool::Microsoft::Stitch',
  1134. ByteOrder => 'LittleEndian', #PH (NC)
  1135. },
  1136. },
  1137. 0x4749 => 'RatingPercent', #PH
  1138. 0x7035 => 'ChromaticAberrationCorrParams', #forum6509 (Sony A7 ARW)
  1139. 0x7037 => 'DistortionCorrParams', #forum6509 (Sony A7 ARW)
  1140. 0x800d => 'ImageID', #10
  1141. 0x80a3 => { Name => 'WangTag1', Binary => 1 }, #20
  1142. 0x80a4 => { Name => 'WangAnnotation', Binary => 1 },
  1143. 0x80a5 => { Name => 'WangTag3', Binary => 1 }, #20
  1144. 0x80a6 => { #20
  1145. Name => 'WangTag4',
  1146. PrintConv => 'length($val) <= 64 ? $val : \$val',
  1147. },
  1148. # tags 0x80b8-0x80bb are registered to Island Graphics
  1149. 0x80b8 => 'ImageReferencePoints', #29
  1150. 0x80b9 => 'RegionXformTackPoint', #29
  1151. 0x80ba => 'WarpQuadrilateral', #29
  1152. 0x80bb => 'AffineTransformMat', #29
  1153. 0x80e3 => 'Matteing', #9
  1154. 0x80e4 => 'DataType', #9
  1155. 0x80e5 => 'ImageDepth', #9
  1156. 0x80e6 => 'TileDepth', #9
  1157. # tags 0x8214-0x8219 are registered to Pixar
  1158. 0x8214 => 'ImageFullWidth', #29
  1159. 0x8215 => 'ImageFullHeight', #29
  1160. 0x8216 => 'TextureFormat', #29
  1161. 0x8217 => 'WrapModes', #29
  1162. 0x8218 => 'FovCot', #29
  1163. 0x8219 => 'MatrixWorldToScreen', #29
  1164. 0x821a => 'MatrixWorldToCamera', #29
  1165. 0x827d => 'Model2', #29 (Eastman Kodak)
  1166. 0x828d => 'CFARepeatPatternDim', #12
  1167. 0x828e => {
  1168. Name => 'CFAPattern2', #12
  1169. Format => 'int8u', # (written incorrectly as 'undef' in Nikon NRW images)
  1170. },
  1171. 0x828f => { #12
  1172. Name => 'BatteryLevel',
  1173. Groups => { 2 => 'Camera' },
  1174. },
  1175. 0x8290 => {
  1176. Name => 'KodakIFD',
  1177. Groups => { 1 => 'KodakIFD' },
  1178. Flags => 'SubIFD',
  1179. Notes => 'used in various types of Kodak images',
  1180. SubDirectory => {
  1181. TagTable => 'Image::ExifTool::Kodak::IFD',
  1182. DirName => 'KodakIFD',
  1183. Start => '$val',
  1184. MaxSubdirs => 1,
  1185. },
  1186. },
  1187. 0x8298 => {
  1188. Name => 'Copyright',
  1189. Groups => { 2 => 'Author' },
  1190. Format => 'undef',
  1191. Notes => q{
  1192. may contain copyright notices for photographer and editor, separated by a
  1193. newline. As per the EXIF specification, the newline is replaced by a null
  1194. byte when writing to file, but this may be avoided by disabling the print
  1195. conversion
  1196. },
  1197. # internally the strings are separated by a null character in this format:
  1198. # Photographer only: photographer + NULL
  1199. # Both: photographer + NULL + editor + NULL
  1200. # Editor only: SPACE + NULL + editor + NULL
  1201. # (this is done as a RawConv so conditional replaces will work properly)
  1202. RawConv => sub {
  1203. my ($val, $self) = @_;
  1204. $val =~ s/ *\0/\n/; # translate first NULL to a newline, removing trailing blanks
  1205. $val =~ s/ *\0.*//s; # truncate at second NULL and remove trailing blanks
  1206. $val =~ s/\n$//; # remove trailing newline if it exists
  1207. # decode if necessary (note: this is the only non-'string' EXIF value like this)
  1208. my $enc = $self->Options('CharsetEXIF');
  1209. $val = $self->Decode($val,$enc) if $enc;
  1210. return $val;
  1211. },
  1212. },
  1213. 0x829a => {
  1214. Name => 'ExposureTime',
  1215. PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
  1216. },
  1217. 0x829d => {
  1218. Name => 'FNumber',
  1219. PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
  1220. },
  1221. 0x82a5 => { #3
  1222. Name => 'MDFileTag',
  1223. Notes => 'tags 0x82a5-0x82ac are used in Molecular Dynamics GEL files',
  1224. },
  1225. 0x82a6 => 'MDScalePixel', #3
  1226. 0x82a7 => 'MDColorTable', #3
  1227. 0x82a8 => 'MDLabName', #3
  1228. 0x82a9 => 'MDSampleInfo', #3
  1229. 0x82aa => 'MDPrepDate', #3
  1230. 0x82ab => 'MDPrepTime', #3
  1231. 0x82ac => 'MDFileUnits', #3
  1232. 0x830e => 'PixelScale',
  1233. 0x8335 => 'AdventScale', #20
  1234. 0x8336 => 'AdventRevision', #20
  1235. 0x835c => 'UIC1Tag', #23
  1236. 0x835d => 'UIC2Tag', #23
  1237. 0x835e => 'UIC3Tag', #23
  1238. 0x835f => 'UIC4Tag', #23
  1239. 0x83bb => { #12
  1240. Name => 'IPTC-NAA', # (writable directory! -- but see note below)
  1241. # this should actually be written as 'undef' (see
  1242. # http://www.awaresystems.be/imaging/tiff/tifftags/iptc.html),
  1243. # but Photoshop writes it as int32u and Nikon Capture won't read
  1244. # anything else, so we do the same thing here... Doh!
  1245. Format => 'undef', # convert binary values as undef
  1246. Writable => 'int32u', # but write int32u format code in IFD
  1247. WriteGroup => 'IFD0',
  1248. Flags => [ 'Binary', 'Protected' ],
  1249. SubDirectory => {
  1250. DirName => 'IPTC',
  1251. TagTable => 'Image::ExifTool::IPTC::Main',
  1252. },
  1253. # Note: This directory may be written as a block via the IPTC-NAA tag,
  1254. # but this technique is not recommended. Instead, it is better to
  1255. # write the Extra IPTC tag and let ExifTool decide where it should go.
  1256. },
  1257. 0x847e => 'IntergraphPacketData', #3
  1258. 0x847f => 'IntergraphFlagRegisters', #3
  1259. 0x8480 => 'IntergraphMatrix',
  1260. 0x8481 => 'INGRReserved', #20
  1261. 0x8482 => {
  1262. Name => 'ModelTiePoint',
  1263. Groups => { 2 => 'Location' },
  1264. },
  1265. 0x84e0 => 'Site', #9
  1266. 0x84e1 => 'ColorSequence', #9
  1267. 0x84e2 => 'IT8Header', #9
  1268. 0x84e3 => { #9
  1269. Name => 'RasterPadding',
  1270. PrintConv => { #20
  1271. 0 => 'Byte',
  1272. 1 => 'Word',
  1273. 2 => 'Long Word',
  1274. 9 => 'Sector',
  1275. 10 => 'Long Sector',
  1276. },
  1277. },
  1278. 0x84e4 => 'BitsPerRunLength', #9
  1279. 0x84e5 => 'BitsPerExtendedRunLength', #9
  1280. 0x84e6 => 'ColorTable', #9
  1281. 0x84e7 => { #9
  1282. Name => 'ImageColorIndicator',
  1283. PrintConv => { #20
  1284. 0 => 'Unspecified Image Color',
  1285. 1 => 'Specified Image Color',
  1286. },
  1287. },
  1288. 0x84e8 => { #9
  1289. Name => 'BackgroundColorIndicator',
  1290. PrintConv => { #20
  1291. 0 => 'Unspecified Background Color',
  1292. 1 => 'Specified Background Color',
  1293. },
  1294. },
  1295. 0x84e9 => 'ImageColorValue', #9
  1296. 0x84ea => 'BackgroundColorValue', #9
  1297. 0x84eb => 'PixelIntensityRange', #9
  1298. 0x84ec => 'TransparencyIndicator', #9
  1299. 0x84ed => 'ColorCharacterization', #9
  1300. 0x84ee => { #9
  1301. Name => 'HCUsage',
  1302. PrintConv => { #20
  1303. 0 => 'CT',
  1304. 1 => 'Line Art',
  1305. 2 => 'Trap',
  1306. },
  1307. },
  1308. 0x84ef => 'TrapIndicator', #17
  1309. 0x84f0 => 'CMYKEquivalent', #17
  1310. 0x8546 => { #11
  1311. Name => 'SEMInfo',
  1312. Notes => 'found in some scanning electron microscope images',
  1313. },
  1314. 0x8568 => {
  1315. Name => 'AFCP_IPTC',
  1316. SubDirectory => {
  1317. # must change directory name so we don't create this directory
  1318. DirName => 'AFCP_IPTC',
  1319. TagTable => 'Image::ExifTool::IPTC::Main',
  1320. },
  1321. },
  1322. 0x85b8 => 'PixelMagicJBIGOptions', #20
  1323. 0x85d7 => 'JPLCartoIFD', #exifprobe (NC)
  1324. 0x85d8 => {
  1325. Name => 'ModelTransform',
  1326. Groups => { 2 => 'Location' },
  1327. },
  1328. 0x8602 => { #16
  1329. Name => 'WB_GRGBLevels',
  1330. Notes => 'found in IFD0 of Leaf MOS images',
  1331. },
  1332. # 0x8603 - Leaf CatchLight color matrix (ref 16)
  1333. 0x8606 => {
  1334. Name => 'LeafData',
  1335. Format => 'undef', # avoid converting huge block to string of int8u's!
  1336. SubDirectory => {
  1337. DirName => 'LeafIFD',
  1338. TagTable => 'Image::ExifTool::Leaf::Main',
  1339. },
  1340. },
  1341. 0x8649 => { #19
  1342. Name => 'PhotoshopSettings',
  1343. Format => 'binary',
  1344. SubDirectory => {
  1345. DirName => 'Photoshop',
  1346. TagTable => 'Image::ExifTool::Photoshop::Main',
  1347. },
  1348. },
  1349. 0x8769 => {
  1350. Name => 'ExifOffset',
  1351. Groups => { 1 => 'ExifIFD' },
  1352. SubIFD => 2,
  1353. SubDirectory => {
  1354. DirName => 'ExifIFD',
  1355. Start => '$val',
  1356. },
  1357. },
  1358. 0x8773 => {
  1359. Name => 'ICC_Profile',
  1360. SubDirectory => {
  1361. TagTable => 'Image::ExifTool::ICC_Profile::Main',
  1362. },
  1363. },
  1364. 0x877f => { #20
  1365. Name => 'TIFF_FXExtensions',
  1366. PrintConv => { BITMASK => {
  1367. 0 => 'Resolution/Image Width',
  1368. 1 => 'N Layer Profile M',
  1369. 2 => 'Shared Data',
  1370. 3 => 'B&W JBIG2',
  1371. 4 => 'JBIG2 Profile M',
  1372. }},
  1373. },
  1374. 0x8780 => { #20
  1375. Name => 'MultiProfiles',
  1376. PrintConv => { BITMASK => {
  1377. 0 => 'Profile S',
  1378. 1 => 'Profile F',
  1379. 2 => 'Profile J',
  1380. 3 => 'Profile C',
  1381. 4 => 'Profile L',
  1382. 5 => 'Profile M',
  1383. 6 => 'Profile T',
  1384. 7 => 'Resolution/Image Width',
  1385. 8 => 'N Layer Profile M',
  1386. 9 => 'Shared Data',
  1387. 10 => 'JBIG2 Profile M',
  1388. }},
  1389. },
  1390. 0x8781 => { #22
  1391. Name => 'SharedData',
  1392. IsOffset => 1,
  1393. # this tag is not supported for writing, so define an
  1394. # invalid offset pair to cause a "No size tag" error to be
  1395. # generated if we try to write a file containing this tag
  1396. OffsetPair => -1,
  1397. },
  1398. 0x8782 => 'T88Options', #20
  1399. 0x87ac => 'ImageLayer',
  1400. 0x87af => {
  1401. Name => 'GeoTiffDirectory',
  1402. Format => 'undef',
  1403. Binary => 1,
  1404. Notes => q{
  1405. these "GeoTiff" tags may read and written as a block, but they aren't
  1406. extracted unless specifically requested. Byte order changes are handled
  1407. automatically when copying between TIFF images with different byte order
  1408. },
  1409. RawConv => '$val . GetByteOrder()', # save byte order
  1410. },
  1411. 0x87b0 => {
  1412. Name => 'GeoTiffDoubleParams',
  1413. Format => 'undef',
  1414. Binary => 1,
  1415. RawConv => '$val . GetByteOrder()', # save byte order
  1416. },
  1417. 0x87b1 => {
  1418. Name => 'GeoTiffAsciiParams',
  1419. Binary => 1,
  1420. },
  1421. 0x87be => 'JBIGOptions', #29
  1422. 0x8822 => {
  1423. Name => 'ExposureProgram',
  1424. Groups => { 2 => 'Camera' },
  1425. Notes => 'the value of 9 is not standard EXIF, but is used by the Canon EOS 7D',
  1426. PrintConv => {
  1427. 0 => 'Not Defined',
  1428. 1 => 'Manual',
  1429. 2 => 'Program AE',
  1430. 3 => 'Aperture-priority AE',
  1431. 4 => 'Shutter speed priority AE',
  1432. 5 => 'Creative (Slow speed)',
  1433. 6 => 'Action (High speed)',
  1434. 7 => 'Portrait',
  1435. 8 => 'Landscape',
  1436. 9 => 'Bulb', #25
  1437. },
  1438. },
  1439. 0x8824 => {
  1440. Name => 'SpectralSensitivity',
  1441. Groups => { 2 => 'Camera' },
  1442. },
  1443. 0x8825 => {
  1444. Name => 'GPSInfo',
  1445. Groups => { 1 => 'GPS' },
  1446. Flags => 'SubIFD',
  1447. SubDirectory => {
  1448. DirName => 'GPS',
  1449. TagTable => 'Image::ExifTool::GPS::Main',
  1450. Start => '$val',
  1451. MaxSubdirs => 1,
  1452. },
  1453. },
  1454. 0x8827 => {
  1455. Name => 'ISO',
  1456. Notes => q{
  1457. called ISOSpeedRatings by EXIF 2.2, then PhotographicSensitivity by the EXIF
  1458. 2.3 spec.
  1459. },
  1460. PrintConv => '$val=~s/\s+/, /g; $val',
  1461. },
  1462. 0x8828 => {
  1463. Name => 'Opto-ElectricConvFactor',
  1464. Notes => 'called OECF by the EXIF spec.',
  1465. Binary => 1,
  1466. },
  1467. 0x8829 => 'Interlace', #12
  1468. 0x882a => 'TimeZoneOffset', #12
  1469. 0x882b => 'SelfTimerMode', #12
  1470. 0x8830 => { #24
  1471. Name => 'SensitivityType',
  1472. Notes => 'applies to EXIF:ISO tag',
  1473. PrintConv => {
  1474. 0 => 'Unknown',
  1475. 1 => 'Standard Output Sensitivity',
  1476. 2 => 'Recommended Exposure Index',
  1477. 3 => 'ISO Speed',
  1478. 4 => 'Standard Output Sensitivity and Recommended Exposure Index',
  1479. 5 => 'Standard Output Sensitivity and ISO Speed',
  1480. 6 => 'Recommended Exposure Index and ISO Speed',
  1481. 7 => 'Standard Output Sensitivity, Recommended Exposure Index and ISO Speed',
  1482. },
  1483. },
  1484. 0x8831 => 'StandardOutputSensitivity', #24
  1485. 0x8832 => 'RecommendedExposureIndex', #24
  1486. 0x8833 => 'ISOSpeed', #24
  1487. 0x8834 => { #24
  1488. Name => 'ISOSpeedLatitudeyyy',
  1489. Description => 'ISO Speed Latitude yyy',
  1490. },
  1491. 0x8835 => { #24
  1492. Name => 'ISOSpeedLatitudezzz',
  1493. Description => 'ISO Speed Latitude zzz',
  1494. },
  1495. 0x885c => 'FaxRecvParams', #9
  1496. 0x885d => 'FaxSubAddress', #9
  1497. 0x885e => 'FaxRecvTime', #9
  1498. 0x8871 => 'FedexEDR', #exifprobe (NC)
  1499. 0x888a => { #PH
  1500. Name => 'LeafSubIFD',
  1501. Format => 'int32u', # Leaf incorrectly uses 'undef' format!
  1502. Groups => { 1 => 'LeafSubIFD' },
  1503. Flags => 'SubIFD',
  1504. SubDirectory => {
  1505. TagTable => 'Image::ExifTool::Leaf::SubIFD',
  1506. Start => '$val',
  1507. },
  1508. },
  1509. 0x9000 => {
  1510. Name => 'ExifVersion',
  1511. RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators)
  1512. },
  1513. 0x9003 => {
  1514. Name => 'DateTimeOriginal',
  1515. Description => 'Date/Time Original',
  1516. Groups => { 2 => 'Time' },
  1517. Notes => 'date/time when original image was taken',
  1518. PrintConv => '$self->ConvertDateTime($val)',
  1519. },
  1520. 0x9004 => {
  1521. Name => 'CreateDate',
  1522. Groups => { 2 => 'Time' },
  1523. Notes => 'called DateTimeDigitized by the EXIF spec.',
  1524. PrintConv => '$self->ConvertDateTime($val)',
  1525. },
  1526. 0x9009 => { # undef[44] (or undef[11]) written by Google Plus uploader - PH
  1527. Name => 'GooglePlusUploadCode',
  1528. Format => 'int8u',
  1529. Count => -1,
  1530. },
  1531. 0x9101 => {
  1532. Name => 'ComponentsConfiguration',
  1533. Format => 'int8u',
  1534. PrintConvColumns => 2,
  1535. PrintConv => {
  1536. 0 => '-',
  1537. 1 => 'Y',
  1538. 2 => 'Cb',
  1539. 3 => 'Cr',
  1540. 4 => 'R',
  1541. 5 => 'G',
  1542. 6 => 'B',
  1543. OTHER => sub {
  1544. my ($val, $inv, $conv) = @_;
  1545. my @a = split /,?\s+/, $val;
  1546. if ($inv) {
  1547. my %invConv;
  1548. $invConv{lc $$conv{$_}} = $_ foreach keys %$conv;
  1549. # strings like "YCbCr" and "RGB" still work for writing
  1550. @a = $a[0] =~ /(Y|Cb|Cr|R|G|B)/g if @a == 1;
  1551. foreach (@a) {
  1552. $_ = $invConv{lc $_};
  1553. return undef unless defined $_;
  1554. }
  1555. push @a, 0 while @a < 4;
  1556. } else {
  1557. foreach (@a) {
  1558. $_ = $$conv{$_} || "Err ($_)";
  1559. }
  1560. }
  1561. return join ', ', @a;
  1562. },
  1563. },
  1564. },
  1565. 0x9102 => 'CompressedBitsPerPixel',
  1566. # 0x9103 - int16u: 1 (found in Pentax XG-1 samples)
  1567. 0x9201 => {
  1568. Name => 'ShutterSpeedValue',
  1569. Notes => 'displayed in seconds, but stored as an APEX value',
  1570. Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u)
  1571. ValueConv => 'abs($val)<100 ? 2**(-$val) : 0',
  1572. PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
  1573. },
  1574. 0x9202 => {
  1575. Name => 'ApertureValue',
  1576. Notes => 'displayed as an F number, but stored as an APEX value',
  1577. ValueConv => '2 ** ($val / 2)',
  1578. PrintConv => 'sprintf("%.1f",$val)',
  1579. },
  1580. # Wikipedia: BrightnessValue = Bv = Av + Tv - Sv
  1581. # ExifTool: LightValue = LV = Av + Tv - Sv + 5 (5 is the Sv for ISO 100 in Exif usage)
  1582. 0x9203 => 'BrightnessValue',
  1583. 0x9204 => {
  1584. Name => 'ExposureCompensation',
  1585. Format => 'rational64s', # Leica M8 patch (incorrectly written as rational64u)
  1586. Notes => 'called ExposureBiasValue by the EXIF spec.',
  1587. PrintConv => 'Image::ExifTool::Exif::PrintFraction($val)',
  1588. },
  1589. 0x9205 => {
  1590. Name => 'MaxApertureValue',
  1591. Notes => 'displayed as an F number, but stored as an APEX value',
  1592. Groups => { 2 => 'Camera' },
  1593. ValueConv => '2 ** ($val / 2)',
  1594. PrintConv => 'sprintf("%.1f",$val)',
  1595. },
  1596. 0x9206 => {
  1597. Name => 'SubjectDistance',
  1598. Groups => { 2 => 'Camera' },
  1599. PrintConv => '$val =~ /^(inf|undef)$/ ? $val : "${val} m"',
  1600. },
  1601. 0x9207 => {
  1602. Name => 'MeteringMode',
  1603. Groups => { 2 => 'Camera' },
  1604. PrintConv => {
  1605. 0 => 'Unknown',
  1606. 1 => 'Average',
  1607. 2 => 'Center-weighted average',
  1608. 3 => 'Spot',
  1609. 4 => 'Multi-spot',
  1610. 5 => 'Multi-segment',
  1611. 6 => 'Partial',
  1612. 255 => 'Other',
  1613. },
  1614. },
  1615. 0x9208 => {
  1616. Name => 'LightSource',
  1617. Groups => { 2 => 'Camera' },
  1618. SeparateTable => 'LightSource',
  1619. PrintConv => \%lightSource,
  1620. },
  1621. 0x9209 => {
  1622. Name => 'Flash',
  1623. Groups => { 2 => 'Camera' },
  1624. Flags => 'PrintHex',
  1625. SeparateTable => 'Flash',
  1626. PrintConv => \%flash,
  1627. },
  1628. 0x920a => {
  1629. Name => 'FocalLength',
  1630. Groups => { 2 => 'Camera' },
  1631. PrintConv => 'sprintf("%.1f mm",$val)',
  1632. },
  1633. # Note: tags 0x920b-0x9217 are duplicates of 0xa20b-0xa217
  1634. # (The TIFF standard uses 0xa2xx, but you'll find both in images)
  1635. 0x920b => { #12
  1636. Name => 'FlashEnergy',
  1637. Groups => { 2 => 'Camera' },
  1638. },
  1639. 0x920c => 'SpatialFrequencyResponse', #12 (not in Fuji images - PH)
  1640. 0x920d => 'Noise', #12
  1641. 0x920e => 'FocalPlaneXResolution', #12
  1642. 0x920f => 'FocalPlaneYResolution', #12
  1643. 0x9210 => { #12
  1644. Name => 'FocalPlaneResolutionUnit',
  1645. Groups => { 2 => 'Camera' },
  1646. PrintConv => {
  1647. 1 => 'None',
  1648. 2 => 'inches',
  1649. 3 => 'cm',
  1650. 4 => 'mm',
  1651. 5 => 'um',
  1652. },
  1653. },
  1654. 0x9211 => 'ImageNumber', #12
  1655. 0x9212 => { #12
  1656. Name => 'SecurityClassification',
  1657. PrintConv => {
  1658. T => 'Top Secret',
  1659. S => 'Secret',
  1660. C => 'Confidential',
  1661. R => 'Restricted',
  1662. U => 'Unclassified',
  1663. },
  1664. },
  1665. 0x9213 => 'ImageHistory', #12
  1666. 0x9214 => {
  1667. Name => 'SubjectArea',
  1668. Groups => { 2 => 'Camera' },
  1669. },
  1670. 0x9215 => 'ExposureIndex', #12
  1671. 0x9216 => 'TIFF-EPStandardID', #12
  1672. 0x9217 => { #12
  1673. Name => 'SensingMethod',
  1674. Groups => { 2 => 'Camera' },
  1675. Notes => 'values 1 and 6 are not standard EXIF',
  1676. PrintConv => {
  1677. 1 => 'Monochrome area', #12 (not standard EXIF)
  1678. 2 => 'One-chip color area',
  1679. 3 => 'Two-chip color area',
  1680. 4 => 'Three-chip color area',
  1681. 5 => 'Color sequential area',
  1682. 6 => 'Monochrome linear', #12 (not standard EXIF)
  1683. 7 => 'Trilinear',
  1684. 8 => 'Color sequential linear',
  1685. },
  1686. },
  1687. 0x923a => 'CIP3DataFile', #20
  1688. 0x923b => 'CIP3Sheet', #20
  1689. 0x923c => 'CIP3Side', #20
  1690. 0x923f => 'StoNits', #9
  1691. # handle maker notes as a conditional list
  1692. 0x927c => \@Image::ExifTool::MakerNotes::Main,
  1693. 0x9286 => {
  1694. Name => 'UserComment',
  1695. # I have seen other applications write it incorrectly as 'string' or 'int8u'
  1696. Format => 'undef',
  1697. RawConv => 'Image::ExifTool::Exif::ConvertExifText($self,$val,1,$tag)',
  1698. },
  1699. 0x9290 => {
  1700. Name => 'SubSecTime',
  1701. Groups => { 2 => 'Time' },
  1702. ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks
  1703. },
  1704. 0x9291 => {
  1705. Name => 'SubSecTimeOriginal',
  1706. Groups => { 2 => 'Time' },
  1707. ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks
  1708. },
  1709. 0x9292 => {
  1710. Name => 'SubSecTimeDigitized',
  1711. Groups => { 2 => 'Time' },
  1712. ValueConv => '$val=~s/ +$//; $val', # trim trailing blanks
  1713. },
  1714. # The following 3 tags are found in MSOffice TIFF images
  1715. # References:
  1716. # http://social.msdn.microsoft.com/Forums/en-US/os_standocs/thread/03086d55-294a-49d5-967a-5303d34c40f8/
  1717. # http://blogs.msdn.com/openspecification/archive/2009/12/08/details-of-three-tiff-tag-extensions-that-microsoft-office-document-imaging-modi-software-may-write-into-the-tiff-files-it-generates.aspx
  1718. # http://www.microsoft.com/downloads/details.aspx?FamilyID=0dbc435d-3544-4f4b-9092-2f2643d64a39&displaylang=en#filelist
  1719. 0x932f => 'MSDocumentText',
  1720. 0x9330 => {
  1721. Name => 'MSPropertySetStorage',
  1722. Binary => 1,
  1723. },
  1724. 0x9331 => {
  1725. Name => 'MSDocumentTextPosition',
  1726. Binary => 1, # (just in case -- don't know what format this is)
  1727. },
  1728. 0x935c => { #3/19
  1729. Name => 'ImageSourceData',
  1730. Binary => 1,
  1731. Protected => 1, # (because this can be hundreds of megabytes)
  1732. },
  1733. 0x9c9b => {
  1734. Name => 'XPTitle',
  1735. Format => 'undef',
  1736. ValueConv => '$self->Decode($val,"UCS2","II")',
  1737. },
  1738. 0x9c9c => {
  1739. Name => 'XPComment',
  1740. Format => 'undef',
  1741. ValueConv => '$self->Decode($val,"UCS2","II")',
  1742. },
  1743. 0x9c9d => {
  1744. Name => 'XPAuthor',
  1745. Groups => { 2 => 'Author' },
  1746. Format => 'undef',
  1747. ValueConv => '$self->Decode($val,"UCS2","II")',
  1748. },
  1749. 0x9c9e => {
  1750. Name => 'XPKeywords',
  1751. Format => 'undef',
  1752. ValueConv => '$self->Decode($val,"UCS2","II")',
  1753. },
  1754. 0x9c9f => {
  1755. Name => 'XPSubject',
  1756. Format => 'undef',
  1757. ValueConv => '$self->Decode($val,"UCS2","II")',
  1758. },
  1759. 0xa000 => {
  1760. Name => 'FlashpixVersion',
  1761. RawConv => '$val=~s/\0+$//; $val', # (some idiots add null terminators)
  1762. },
  1763. 0xa001 => {
  1764. Name => 'ColorSpace',
  1765. Notes => q{
  1766. the value of 0x2 is not standard EXIF. Instead, an Adobe RGB image is
  1767. indicated by "Uncalibrated" with an InteropIndex of "R03". The values
  1768. 0xfffd and 0xfffe are also non-standard, and are used by some Sony cameras
  1769. },
  1770. PrintHex => 1,
  1771. PrintConv => {
  1772. 1 => 'sRGB',
  1773. 2 => 'Adobe RGB',
  1774. 0xffff => 'Uncalibrated',
  1775. # Sony uses these definitions: (ref JD)
  1776. # 0xffff => 'Adobe RGB', (conflicts with Uncalibrated)
  1777. 0xfffe => 'ICC Profile',
  1778. 0xfffd => 'Wide Gamut RGB',
  1779. },
  1780. },
  1781. 0xa002 => {
  1782. Name => 'ExifImageWidth',
  1783. Notes => 'called PixelXDimension by the EXIF spec.',
  1784. },
  1785. 0xa003 => {
  1786. Name => 'ExifImageHeight',
  1787. Notes => 'called PixelYDimension by the EXIF spec.',
  1788. },
  1789. 0xa004 => 'RelatedSoundFile',
  1790. 0xa005 => {
  1791. Name => 'InteropOffset',
  1792. Groups => { 1 => 'InteropIFD' },
  1793. Flags => 'SubIFD',
  1794. Description => 'Interoperability Offset',
  1795. SubDirectory => {
  1796. DirName => 'InteropIFD',
  1797. Start => '$val',
  1798. MaxSubdirs => 1,
  1799. },
  1800. },
  1801. 0xa20b => {
  1802. Name => 'FlashEnergy',
  1803. Groups => { 2 => 'Camera' },
  1804. },
  1805. 0xa20c => {
  1806. Name => 'SpatialFrequencyResponse',
  1807. PrintConv => 'Image::ExifTool::Exif::PrintSFR($val)',
  1808. },
  1809. 0xa20d => 'Noise',
  1810. 0xa20e => { Name => 'FocalPlaneXResolution', Groups => { 2 => 'Camera' } },
  1811. 0xa20f => { Name => 'FocalPlaneYResolution', Groups => { 2 => 'Camera' } },
  1812. 0xa210 => {
  1813. Name => 'FocalPlaneResolutionUnit',
  1814. Groups => { 2 => 'Camera' },
  1815. Notes => 'values 1, 4 and 5 are not standard EXIF',
  1816. PrintConv => {
  1817. 1 => 'None', # (not standard EXIF)
  1818. 2 => 'inches',
  1819. 3 => 'cm',
  1820. 4 => 'mm', # (not standard EXIF)
  1821. 5 => 'um', # (not standard EXIF)
  1822. },
  1823. },
  1824. 0xa211 => 'ImageNumber',
  1825. 0xa212 => 'SecurityClassification',
  1826. 0xa213 => 'ImageHistory',
  1827. 0xa214 => {
  1828. Name => 'SubjectLocation',
  1829. Groups => { 2 => 'Camera' },
  1830. },
  1831. 0xa215 => 'ExposureIndex',
  1832. 0xa216 => 'TIFF-EPStandardID',
  1833. 0xa217 => {
  1834. Name => 'SensingMethod',
  1835. Groups => { 2 => 'Camera' },
  1836. PrintConv => {
  1837. 1 => 'Not defined',
  1838. 2 => 'One-chip color area',
  1839. 3 => 'Two-chip color area',
  1840. 4 => 'Three-chip color area',
  1841. 5 => 'Color sequential area',
  1842. 7 => 'Trilinear',
  1843. 8 => 'Color sequential linear',
  1844. },
  1845. },
  1846. 0xa300 => {
  1847. Name => 'FileSource',
  1848. PrintConv => {
  1849. 1 => 'Film Scanner',
  1850. 2 => 'Reflection Print Scanner',
  1851. 3 => 'Digital Camera',
  1852. # handle the case where Sigma incorrectly gives this tag a count of 4
  1853. "\3\0\0\0" => 'Sigma Digital Camera',
  1854. },
  1855. },
  1856. 0xa301 => {
  1857. Name => 'SceneType',
  1858. PrintConv => {
  1859. 1 => 'Directly photographed',
  1860. },
  1861. },
  1862. 0xa302 => {
  1863. Name => 'CFAPattern',
  1864. RawConv => 'Image::ExifTool::Exif::DecodeCFAPattern($self, $val)',
  1865. PrintConv => 'Image::ExifTool::Exif::PrintCFAPattern($val)',
  1866. },
  1867. 0xa401 => {
  1868. Name => 'CustomRendered',
  1869. PrintConv => {
  1870. 0 => 'Normal',
  1871. 1 => 'Custom',
  1872. # 4 - Apple iPhone5c horizontal orientation
  1873. # 6 - Apple iPhone5c panorama
  1874. },
  1875. },
  1876. 0xa402 => {
  1877. Name => 'ExposureMode',
  1878. Groups => { 2 => 'Camera' },
  1879. PrintConv => {
  1880. 0 => 'Auto',
  1881. 1 => 'Manual',
  1882. 2 => 'Auto bracket',
  1883. # have seen 3 from Samsung EX1, NX30, NX200 - PH
  1884. },
  1885. },
  1886. 0xa403 => {
  1887. Name => 'WhiteBalance',
  1888. Groups => { 2 => 'Camera' },
  1889. # set Priority to zero to keep this WhiteBalance from overriding the
  1890. # MakerNotes WhiteBalance, since the MakerNotes WhiteBalance and is more
  1891. # accurate and contains more information (if it exists)
  1892. Priority => 0,
  1893. PrintConv => {
  1894. 0 => 'Auto',
  1895. 1 => 'Manual',
  1896. },
  1897. },
  1898. 0xa404 => {
  1899. Name => 'DigitalZoomRatio',
  1900. Groups => { 2 => 'Camera' },
  1901. },
  1902. 0xa405 => {
  1903. Name => 'FocalLengthIn35mmFormat',
  1904. Notes => 'called FocalLengthIn35mmFilm by the EXIF spec.',
  1905. Groups => { 2 => 'Camera' },
  1906. PrintConv => '"$val mm"',
  1907. },
  1908. 0xa406 => {
  1909. Name => 'SceneCaptureType',
  1910. Groups => { 2 => 'Camera' },
  1911. PrintConv => {
  1912. 0 => 'Standard',
  1913. 1 => 'Landscape',
  1914. 2 => 'Portrait',
  1915. 3 => 'Night',
  1916. # 4 - HDR (Samsung GT-I9300)
  1917. },
  1918. },
  1919. 0xa407 => {
  1920. Name => 'GainControl',
  1921. Groups => { 2 => 'Camera' },
  1922. PrintConv => {
  1923. 0 => 'None',
  1924. 1 => 'Low gain up',
  1925. 2 => 'High gain up',
  1926. 3 => 'Low gain down',
  1927. 4 => 'High gain down',
  1928. },
  1929. },
  1930. 0xa408 => {
  1931. Name => 'Contrast',
  1932. Groups => { 2 => 'Camera' },
  1933. PrintConv => {
  1934. 0 => 'Normal',
  1935. 1 => 'Low',
  1936. 2 => 'High',
  1937. },
  1938. },
  1939. 0xa409 => {
  1940. Name => 'Saturation',
  1941. Groups => { 2 => 'Camera' },
  1942. PrintConv => {
  1943. 0 => 'Normal',
  1944. 1 => 'Low',
  1945. 2 => 'High',
  1946. },
  1947. },
  1948. 0xa40a => {
  1949. Name => 'Sharpness',
  1950. Groups => { 2 => 'Camera' },
  1951. PrintConv => {
  1952. 0 => 'Normal',
  1953. 1 => 'Soft',
  1954. 2 => 'Hard',
  1955. },
  1956. },
  1957. 0xa40b => {
  1958. Name => 'DeviceSettingDescription',
  1959. Groups => { 2 => 'Camera' },
  1960. Binary => 1,
  1961. },
  1962. 0xa40c => {
  1963. Name => 'SubjectDistanceRange',
  1964. Groups => { 2 => 'Camera' },
  1965. PrintConv => {
  1966. 0 => 'Unknown',
  1967. 1 => 'Macro',
  1968. 2 => 'Close',
  1969. 3 => 'Distant',
  1970. },
  1971. },
  1972. # 0xa40d - int16u: 0 (GE E1486 TW)
  1973. # 0xa40e - int16u: 1 (GE E1486 TW)
  1974. 0xa420 => 'ImageUniqueID',
  1975. 0xa430 => { #24
  1976. Name => 'OwnerName',
  1977. Notes => 'called CameraOwnerName by the EXIF spec.',
  1978. },
  1979. 0xa431 => { #24
  1980. Name => 'SerialNumber',
  1981. Notes => 'called BodySerialNumber by the EXIF spec.',
  1982. },
  1983. 0xa432 => { #24
  1984. Name => 'LensInfo',
  1985. Notes => q{
  1986. 4 rational values giving focal and aperture ranges, called LensSpecification
  1987. by the EXIF spec.
  1988. },
  1989. # convert to the form "12-20mm f/3.8-4.5" or "50mm f/1.4"
  1990. PrintConv => \&Image::ExifTool::Exif::PrintLensInfo,
  1991. },
  1992. 0xa433 => 'LensMake', #24
  1993. 0xa434 => 'LensModel', #24
  1994. 0xa435 => 'LensSerialNumber', #24
  1995. 0xa480 => 'GDALMetadata', #3
  1996. 0xa481 => 'GDALNoData', #3
  1997. 0xa500 => 'Gamma',
  1998. 0xafc0 => 'ExpandSoftware', #JD (Opanda)
  1999. 0xafc1 => 'ExpandLens', #JD (Opanda)
  2000. 0xafc2 => 'ExpandFilm', #JD (Opanda)
  2001. 0xafc3 => 'ExpandFilterLens', #JD (Opanda)
  2002. 0xafc4 => 'ExpandScanner', #JD (Opanda)
  2003. 0xafc5 => 'ExpandFlashLamp', #JD (Opanda)
  2004. #
  2005. # Windows Media Photo / HD Photo (WDP/HDP) tags
  2006. #
  2007. 0xbc01 => { #13
  2008. Name => 'PixelFormat',
  2009. PrintHex => 1,
  2010. Format => 'undef',
  2011. Notes => q{
  2012. tags 0xbc** are used in Windows HD Photo (HDP and WDP) images. The actual
  2013. PixelFormat values are 16-byte GUID's but the leading 15 bytes,
  2014. '6fddc324-4e03-4bfe-b1853-d77768dc9', have been removed below to avoid
  2015. unnecessary clutter
  2016. },
  2017. ValueConv => q{
  2018. require Image::ExifTool::ASF;
  2019. $val = Image::ExifTool::ASF::GetGUID($val);
  2020. # GUID's are too long, so remove redundant information
  2021. $val =~ s/^6fddc324-4e03-4bfe-b185-3d77768dc9//i and $val = hex($val);
  2022. return $val;
  2023. },
  2024. PrintConv => {
  2025. 0x0d => '24-bit RGB',
  2026. 0x0c => '24-bit BGR',
  2027. 0x0e => '32-bit BGR',
  2028. 0x15 => '48-bit RGB',
  2029. 0x12 => '48-bit RGB Fixed Point',
  2030. 0x3b => '48-bit RGB Half',
  2031. 0x18 => '96-bit RGB Fixed Point',
  2032. 0x1b => '128-bit RGB Float',
  2033. 0x0f => '32-bit BGRA',
  2034. 0x16 => '64-bit RGBA',
  2035. 0x1d => '64-bit RGBA Fixed Point',
  2036. 0x3a => '64-bit RGBA Half',
  2037. 0x1e => '128-bit RGBA Fixed Point',
  2038. 0x19 => '128-bit RGBA Float',
  2039. 0x10 => '32-bit PBGRA',
  2040. 0x17 => '64-bit PRGBA',
  2041. 0x1a => '128-bit PRGBA Float',
  2042. 0x1c => '32-bit CMYK',
  2043. 0x2c => '40-bit CMYK Alpha',
  2044. 0x1f => '64-bit CMYK',
  2045. 0x2d => '80-bit CMYK Alpha',
  2046. 0x20 => '24-bit 3 Channels',
  2047. 0x21 => '32-bit 4 Channels',
  2048. 0x22 => '40-bit 5 Channels',
  2049. 0x23 => '48-bit 6 Channels',
  2050. 0x24 => '56-bit 7 Channels',
  2051. 0x25 => '64-bit 8 Channels',
  2052. 0x2e => '32-bit 3 Channels Alpha',
  2053. 0x2f => '40-bit 4 Channels Alpha',
  2054. 0x30 => '48-bit 5 Channels Alpha',
  2055. 0x31 => '56-bit 6 Channels Alpha',
  2056. 0x32 => '64-bit 7 Channels Alpha',
  2057. 0x33 => '72-bit 8 Channels Alpha',
  2058. 0x26 => '48-bit 3 Channels',
  2059. 0x27 => '64-bit 4 Channels',
  2060. 0x28 => '80-bit 5 Channels',
  2061. 0x29 => '96-bit 6 Channels',
  2062. 0x2a => '112-bit 7 Channels',
  2063. 0x2b => '128-bit 8 Channels',
  2064. 0x34 => '64-bit 3 Channels Alpha',
  2065. 0x35 => '80-bit 4 Channels Alpha',
  2066. 0x36 => '96-bit 5 Channels Alpha',
  2067. 0x37 => '112-bit 6 Channels Alpha',
  2068. 0x38 => '128-bit 7 Channels Alpha',
  2069. 0x39 => '144-bit 8 Channels Alpha',
  2070. 0x08 => '8-bit Gray',
  2071. 0x0b => '16-bit Gray',
  2072. 0x13 => '16-bit Gray Fixed Point',
  2073. 0x3e => '16-bit Gray Half',
  2074. 0x3f => '32-bit Gray Fixed Point',
  2075. 0x11 => '32-bit Gray Float',
  2076. 0x05 => 'Black & White',
  2077. 0x09 => '16-bit BGR555',
  2078. 0x0a => '16-bit BGR565',
  2079. 0x13 => '32-bit BGR101010',
  2080. 0x3d => '32-bit RGBE',
  2081. },
  2082. },
  2083. 0xbc02 => { #13
  2084. Name => 'Transformation',
  2085. PrintConv => {
  2086. 0 => 'Horizontal (normal)',
  2087. 1 => 'Mirror vertical',
  2088. 2 => 'Mirror horizontal',
  2089. 3 => 'Rotate 180',
  2090. 4 => 'Rotate 90 CW',
  2091. 5 => 'Mirror horizontal and rotate 90 CW',
  2092. 6 => 'Mirror horizontal and rotate 270 CW',
  2093. 7 => 'Rotate 270 CW',
  2094. },
  2095. },
  2096. 0xbc03 => { #13
  2097. Name => 'Uncompressed',
  2098. PrintConv => { 0 => 'No', 1 => 'Yes' },
  2099. },
  2100. 0xbc04 => { #13
  2101. Name => 'ImageType',
  2102. PrintConv => { BITMASK => {
  2103. 0 => 'Preview',
  2104. 1 => 'Page',
  2105. } },
  2106. },
  2107. 0xbc80 => 'ImageWidth', #13
  2108. 0xbc81 => 'ImageHeight', #13
  2109. 0xbc82 => 'WidthResolution', #13
  2110. 0xbc83 => 'HeightResolution', #13
  2111. 0xbcc0 => { #13
  2112. Name => 'ImageOffset',
  2113. IsOffset => 1,
  2114. OffsetPair => 0xbcc1, # point to associated byte count
  2115. },
  2116. 0xbcc1 => { #13
  2117. Name => 'ImageByteCount',
  2118. OffsetPair => 0xbcc0, # point to associated offset
  2119. },
  2120. 0xbcc2 => { #13
  2121. Name => 'AlphaOffset',
  2122. IsOffset => 1,
  2123. OffsetPair => 0xbcc3, # point to associated byte count
  2124. },
  2125. 0xbcc3 => { #13
  2126. Name => 'AlphaByteCount',
  2127. OffsetPair => 0xbcc2, # point to associated offset
  2128. },
  2129. 0xbcc4 => { #13
  2130. Name => 'ImageDataDiscard',
  2131. PrintConv => {
  2132. 0 => 'Full Resolution',
  2133. 1 => 'Flexbits Discarded',
  2134. 2 => 'HighPass Frequency Data Discarded',
  2135. 3 => 'Highpass and LowPass Frequency Data Discarded',
  2136. },
  2137. },
  2138. 0xbcc5 => { #13
  2139. Name => 'AlphaDataDiscard',
  2140. PrintConv => {
  2141. 0 => 'Full Resolution',
  2142. 1 => 'Flexbits Discarded',
  2143. 2 => 'HighPass Frequency Data Discarded',
  2144. 3 => 'Highpass and LowPass Frequency Data Discarded',
  2145. },
  2146. },
  2147. #
  2148. 0xc427 => 'OceScanjobDesc', #3
  2149. 0xc428 => 'OceApplicationSelector', #3
  2150. 0xc429 => 'OceIDNumber', #3
  2151. 0xc42a => 'OceImageLogic', #3
  2152. 0xc44f => { Name => 'Annotations', Binary => 1 }, #7/19
  2153. 0xc4a5 => {
  2154. Name => 'PrintIM', # (writable directory!)
  2155. # must set Writable here so this tag will be saved with MakerNotes option
  2156. Writable => 'undef',
  2157. WriteGroup => 'IFD0',
  2158. Binary => 1,
  2159. # (don't make Binary/Protected because we can't copy individual PrintIM tags anyway)
  2160. Description => 'Print Image Matching',
  2161. SubDirectory => {
  2162. TagTable => 'Image::ExifTool::PrintIM::Main',
  2163. },
  2164. PrintConvInv => '$val =~ /^PrintIM/ ? $val : undef', # quick validation
  2165. },
  2166. 0xc573 => { #PH
  2167. Name => 'OriginalFileName',
  2168. Notes => 'used by some obscure software', # (possibly Swizzy Photosmacker?)
  2169. # (it is a 'string', but obscure, so don't make it writable)
  2170. },
  2171. 0xc580 => { #20
  2172. Name => 'USPTOOriginalContentType',
  2173. PrintConv => {
  2174. 0 => 'Text or Drawing',
  2175. 1 => 'Grayscale',
  2176. 2 => 'Color',
  2177. },
  2178. },
  2179. # 0xc5d8 - found in CR2 images
  2180. # 0xc5d9 - found in CR2 images
  2181. # 0xc5e0 - found in CR2 images
  2182. #
  2183. # DNG tags 0xc6XX and 0xc7XX (ref 2 unless otherwise stated)
  2184. #
  2185. 0xc612 => {
  2186. Name => 'DNGVersion',
  2187. Notes => 'tags 0xc612-0xc7b5 are used in DNG images unless otherwise noted',
  2188. DataMember => 'DNGVersion',
  2189. RawConv => '$$self{DNGVersion} = $val',
  2190. PrintConv => '$val =~ tr/ /./; $val',
  2191. },
  2192. 0xc613 => {
  2193. Name => 'DNGBackwardVersion',
  2194. PrintConv => '$val =~ tr/ /./; $val',
  2195. },
  2196. 0xc614 => 'UniqueCameraModel',
  2197. 0xc615 => {
  2198. Name => 'LocalizedCameraModel',
  2199. Format => 'string',
  2200. PrintConv => '$self->Printable($val, 0)',
  2201. },
  2202. 0xc616 => {
  2203. Name => 'CFAPlaneColor',
  2204. PrintConv => q{
  2205. my @cols = qw(Red Green Blue Cyan Magenta Yellow White);
  2206. my @vals = map { $cols[$_] || "Unknown($_)" } split(' ', $val);
  2207. return join(',', @vals);
  2208. },
  2209. },
  2210. 0xc617 => {
  2211. Name => 'CFALayout',
  2212. PrintConv => {
  2213. 1 => 'Rectangular',
  2214. 2 => 'Even columns offset down 1/2 row',
  2215. 3 => 'Even columns offset up 1/2 row',
  2216. 4 => 'Even rows offset right 1/2 column',
  2217. 5 => 'Even rows offset left 1/2 column',
  2218. # the following are new for DNG 1.3:
  2219. 6 => 'Even rows offset up by 1/2 row, even columns offset left by 1/2 column',
  2220. 7 => 'Even rows offset up by 1/2 row, even columns offset right by 1/2 column',
  2221. 8 => 'Even rows offset down by 1/2 row, even columns offset left by 1/2 column',
  2222. 9 => 'Even rows offset down by 1/2 row, even columns offset right by 1/2 column',
  2223. },
  2224. },
  2225. 0xc618 => { Name => 'LinearizationTable', Binary => 1 },
  2226. 0xc619 => 'BlackLevelRepeatDim',
  2227. 0xc61a => 'BlackLevel',
  2228. 0xc61b => { Name => 'BlackLevelDeltaH', %longBin },
  2229. 0xc61c => { Name => 'BlackLevelDeltaV', %longBin },
  2230. 0xc61d => 'WhiteLevel',
  2231. 0xc61e => 'DefaultScale',
  2232. 0xc61f => 'DefaultCropOrigin',
  2233. 0xc620 => 'DefaultCropSize',
  2234. 0xc621 => 'ColorMatrix1',
  2235. 0xc622 => 'ColorMatrix2',
  2236. 0xc623 => 'CameraCalibration1',
  2237. 0xc624 => 'CameraCalibration2',
  2238. 0xc625 => 'ReductionMatrix1',
  2239. 0xc626 => 'ReductionMatrix2',
  2240. 0xc627 => 'AnalogBalance',
  2241. 0xc628 => 'AsShotNeutral',
  2242. 0xc629 => 'AsShotWhiteXY',
  2243. 0xc62a => 'BaselineExposure',
  2244. 0xc62b => 'BaselineNoise',
  2245. 0xc62c => 'BaselineSharpness',
  2246. 0xc62d => 'BayerGreenSplit',
  2247. 0xc62e => 'LinearResponseLimit',
  2248. 0xc62f => {
  2249. Name => 'CameraSerialNumber',
  2250. Groups => { 2 => 'Camera' },
  2251. },
  2252. 0xc630 => {
  2253. Name => 'DNGLensInfo',
  2254. Groups => { 2 => 'Camera' },
  2255. PrintConv =>\&PrintLensInfo,
  2256. },
  2257. 0xc631 => 'ChromaBlurRadius',
  2258. 0xc632 => 'AntiAliasStrength',
  2259. 0xc633 => 'ShadowScale',
  2260. 0xc634 => [
  2261. {
  2262. Condition => '$$self{TIFF_TYPE} =~ /^(ARW|SR2)$/',
  2263. Name => 'SR2Private',
  2264. Groups => { 1 => 'SR2' },
  2265. Flags => 'SubIFD',
  2266. Format => 'int32u',
  2267. # some utilites have problems unless this is int8u format:
  2268. # - Adobe Camera Raw 5.3 gives an error
  2269. # - Apple Preview 10.5.8 gets the wrong white balance
  2270. FixFormat => 'int8u', # (stupid Sony)
  2271. SubDirectory => {
  2272. DirName => 'SR2Private',
  2273. TagTable => 'Image::ExifTool::Sony::SR2Private',
  2274. Start => '$val',
  2275. },
  2276. },
  2277. {
  2278. Condition => '$$valPt =~ /^Adobe\0/',
  2279. Name => 'DNGAdobeData',
  2280. Flags => [ 'Binary', 'Protected' ],
  2281. Writable => 'undef', # (writable directory!) (to make it possible to delete this mess)
  2282. WriteGroup => 'IFD0',
  2283. NestedHtmlDump => 1,
  2284. SubDirectory => { TagTable => 'Image::ExifTool::DNG::AdobeData' },
  2285. Format => 'undef', # written incorrectly as int8u (change to undef for speed)
  2286. },
  2287. {
  2288. # Pentax/Samsung models that write AOC maker notes in JPG images:
  2289. # K-5,K-7,K-m,K-x,K-r,K10D,K20D,K100D,K110D,K200D,K2000,GX10,GX20
  2290. # (Note: the following expression also appears in WriteExif.pl)
  2291. Condition => q{
  2292. $$valPt =~ /^(PENTAX |SAMSUNG)\0/ and
  2293. $$self{Model} =~ /\b(K(-[57mrx]|(10|20|100|110|200)D|2000)|GX(10|20))\b/
  2294. },
  2295. Name => 'MakerNotePentax',
  2296. MakerNotes => 1, # (causes "MakerNotes header" to be identified in HtmlDump output)
  2297. Binary => 1,
  2298. # Note: Don't make this block-writable for a few reasons:
  2299. # 1) It would be dangerous (possibly confusing Pentax software)
  2300. # 2) It is a different format from the JPEG version of MakerNotePentax
  2301. # 3) It is converted to JPEG format by RebuildMakerNotes() when copying
  2302. SubDirectory => {
  2303. TagTable => 'Image::ExifTool::Pentax::Main',
  2304. Start => '$valuePtr + 10',
  2305. Base => '$start - 10',
  2306. ByteOrder => 'Unknown', # easier to do this than read byteorder word
  2307. },
  2308. Format => 'undef', # written incorrectly as int8u (change to undef for speed)
  2309. },
  2310. {
  2311. # must duplicate the above tag with a different name for more recent
  2312. # Pentax models which use the "PENTAX" instead of the "AOC" maker notes
  2313. # in JPG images (needed when copying maker notes from DNG to JPG)
  2314. Condition => '$$valPt =~ /^(PENTAX |SAMSUNG)\0/',
  2315. Name => 'MakerNotePentax5',
  2316. MakerNotes => 1,
  2317. Binary => 1,
  2318. SubDirectory => {
  2319. TagTable => 'Image::ExifTool::Pentax::Main',
  2320. Start => '$valuePtr + 10',
  2321. Base => '$start - 10',
  2322. ByteOrder => 'Unknown',
  2323. },
  2324. Format => 'undef',
  2325. },
  2326. {
  2327. Name => 'DNGPrivateData',
  2328. Flags => [ 'Binary', 'Protected' ],
  2329. Format => 'undef',
  2330. Writable => 'undef',
  2331. WriteGroup => 'IFD0',
  2332. },
  2333. ],
  2334. 0xc635 => {
  2335. Name => 'MakerNoteSafety',
  2336. PrintConv => {
  2337. 0 => 'Unsafe',
  2338. 1 => 'Safe',
  2339. },
  2340. },
  2341. 0xc640 => { #15
  2342. Name => 'RawImageSegmentation',
  2343. # (int16u[3], not writable)
  2344. Notes => q{
  2345. used in segmented Canon CR2 images. 3 numbers: 1. Number of segments minus
  2346. one; 2. Pixel width of segments except last; 3. Pixel width of last segment
  2347. },
  2348. },
  2349. 0xc65a => {
  2350. Name => 'CalibrationIlluminant1',
  2351. SeparateTable => 'LightSource',
  2352. PrintConv => \%lightSource,
  2353. },
  2354. 0xc65b => {
  2355. Name => 'CalibrationIlluminant2',
  2356. SeparateTable => 'LightSource',
  2357. PrintConv => \%lightSource,
  2358. },
  2359. 0xc65c => 'BestQualityScale',
  2360. 0xc65d => {
  2361. Name => 'RawDataUniqueID',
  2362. Format => 'undef',
  2363. ValueConv => 'uc(unpack("H*",$val))',
  2364. },
  2365. 0xc660 => { #3
  2366. Name => 'AliasLayerMetadata',
  2367. Notes => 'used by Alias Sketchbook Pro',
  2368. },
  2369. 0xc68b => {
  2370. Name => 'OriginalRawFileName',
  2371. Format => 'string', # sometimes written as int8u
  2372. },
  2373. 0xc68c => {
  2374. Name => 'OriginalRawFileData', # (writable directory!)
  2375. Writable => 'undef', # must be defined here so tag will be extracted if specified
  2376. WriteGroup => 'IFD0',
  2377. Flags => [ 'Binary', 'Protected' ],
  2378. SubDirectory => {
  2379. TagTable => 'Image::ExifTool::DNG::OriginalRaw',
  2380. },
  2381. },
  2382. 0xc68d => 'ActiveArea',
  2383. 0xc68e => 'MaskedAreas',
  2384. 0xc68f => {
  2385. Name => 'AsShotICCProfile',
  2386. Binary => 1,
  2387. Writable => 'undef', # must be defined here so tag will be extracted if specified
  2388. SubDirectory => {
  2389. DirName => 'AsShotICCProfile',
  2390. TagTable => 'Image::ExifTool::ICC_Profile::Main',
  2391. },
  2392. },
  2393. 0xc690 => 'AsShotPreProfileMatrix',
  2394. 0xc691 => {
  2395. Name => 'CurrentICCProfile',
  2396. Binary => 1,
  2397. Writable => 'undef', # must be defined here so tag will be extracted if specified
  2398. SubDirectory => {
  2399. DirName => 'CurrentICCProfile',
  2400. TagTable => 'Image::ExifTool::ICC_Profile::Main',
  2401. },
  2402. },
  2403. 0xc692 => 'CurrentPreProfileMatrix',
  2404. 0xc6bf => 'ColorimetricReference',
  2405. 0xc6d2 => { #JD (Panasonic DMC-TZ5)
  2406. # this text is UTF-8 encoded (hooray!) - PH (TZ5)
  2407. Name => 'PanasonicTitle',
  2408. Format => 'string', # written incorrectly as 'undef'
  2409. Notes => 'proprietary Panasonic tag used for baby/pet name, etc',
  2410. # panasonic always records this tag (64 zero bytes),
  2411. # so ignore it unless it contains valid information
  2412. RawConv => 'length($val) ? $val : undef',
  2413. ValueConv => '$self->Decode($val, "UTF8")',
  2414. },
  2415. 0xc6c5 => { Name => 'SRawType', Description => 'SRaw Type' }, #exifprobe (CR2 proprietary)
  2416. 0xc6d3 => { #PH (Panasonic DMC-FS7)
  2417. Name => 'PanasonicTitle2',
  2418. Format => 'string', # written incorrectly as 'undef'
  2419. Notes => 'proprietary Panasonic tag used for baby/pet name with age',
  2420. # panasonic always records this tag (128 zero bytes),
  2421. # so ignore it unless it contains valid information
  2422. RawConv => 'length($val) ? $val : undef',
  2423. ValueConv => '$self->Decode($val, "UTF8")',
  2424. },
  2425. # 0xc6dc - int32u[4]: found in CR2 images (PH, 7DmkIII)
  2426. 0xc6f3 => 'CameraCalibrationSig',
  2427. 0xc6f4 => 'ProfileCalibrationSig',
  2428. 0xc6f5 => {
  2429. Name => 'ProfileIFD', # (ExtraCameraProfiles)
  2430. Groups => { 1 => 'ProfileIFD' },
  2431. Flags => 'SubIFD',
  2432. SubDirectory => {
  2433. ProcessProc => \&ProcessTiffIFD,
  2434. WriteProc => \&ProcessTiffIFD,
  2435. DirName => 'ProfileIFD',
  2436. Start => '$val',
  2437. Base => '$start', # offsets relative to start of TIFF-like header
  2438. MaxSubdirs => 10,
  2439. Magic => 0x4352, # magic number for TIFF-like header
  2440. },
  2441. },
  2442. 0xc6f6 => 'AsShotProfileName',
  2443. 0xc6f7 => 'NoiseReductionApplied',
  2444. 0xc6f8 => 'ProfileName',
  2445. 0xc6f9 => 'ProfileHueSatMapDims',
  2446. 0xc6fa => { Name => 'ProfileHueSatMapData1', %longBin },
  2447. 0xc6fb => { Name => 'ProfileHueSatMapData2', %longBin },
  2448. 0xc6fc => {
  2449. Name => 'ProfileToneCurve',
  2450. Binary => 1,
  2451. },
  2452. 0xc6fd => {
  2453. Name => 'ProfileEmbedPolicy',
  2454. PrintConv => {
  2455. 0 => 'Allow Copying',
  2456. 1 => 'Embed if Used',
  2457. 2 => 'Never Embed',
  2458. 3 => 'No Restrictions',
  2459. },
  2460. },
  2461. 0xc6fe => 'ProfileCopyright',
  2462. 0xc714 => 'ForwardMatrix1',
  2463. 0xc715 => 'ForwardMatrix2',
  2464. 0xc716 => 'PreviewApplicationName',
  2465. 0xc717 => 'PreviewApplicationVersion',
  2466. 0xc718 => 'PreviewSettingsName',
  2467. 0xc719 => {
  2468. Name => 'PreviewSettingsDigest',
  2469. Format => 'undef',
  2470. ValueConv => 'unpack("H*", $val)',
  2471. },
  2472. 0xc71a => 'PreviewColorSpace',
  2473. 0xc71b => {
  2474. Name => 'PreviewDateTime',
  2475. Groups => { 2 => 'Time' },
  2476. ValueConv => q{
  2477. require Image::ExifTool::XMP;
  2478. return Image::ExifTool::XMP::ConvertXMPDate($val);
  2479. },
  2480. },
  2481. 0xc71c => {
  2482. Name => 'RawImageDigest',
  2483. Format => 'undef',
  2484. ValueConv => 'unpack("H*", $val)',
  2485. },
  2486. 0xc71d => {
  2487. Name => 'OriginalRawFileDigest',
  2488. Format => 'undef',
  2489. ValueConv => 'unpack("H*", $val)',
  2490. },
  2491. 0xc71e => 'SubTileBlockSize',
  2492. 0xc71f => 'RowInterleaveFactor',
  2493. 0xc725 => 'ProfileLookTableDims',
  2494. 0xc726 => {
  2495. Name => 'ProfileLookTableData',
  2496. Binary => 1,
  2497. },
  2498. 0xc740 => { # DNG 1.3
  2499. Name => 'OpcodeList1',
  2500. Binary => 1,
  2501. # opcodes:
  2502. # 1 => 'WarpRectilinear',
  2503. # 2 => 'WarpFisheye',
  2504. # 3 => 'FixVignetteRadial',
  2505. # 4 => 'FixBadPixelsConstant',
  2506. # 5 => 'FixBadPixelsList',
  2507. # 6 => 'TrimBounds',
  2508. # 7 => 'MapTable',
  2509. # 8 => 'MapPolynomial',
  2510. # 9 => 'GainMap',
  2511. # 10 => 'DeltaPerRow',
  2512. # 11 => 'DeltaPerColumn',
  2513. # 12 => 'ScalePerRow',
  2514. # 13 => 'ScalePerColumn',
  2515. },
  2516. 0xc741 => { # DNG 1.3
  2517. Name => 'OpcodeList2',
  2518. Binary => 1,
  2519. },
  2520. 0xc74e => { # DNG 1.3
  2521. Name => 'OpcodeList3',
  2522. Binary => 1,
  2523. },
  2524. 0xc761 => 'NoiseProfile', # DNG 1.3
  2525. 0xc763 => { #28
  2526. Name => 'TimeCodes',
  2527. ValueConv => q{
  2528. my @a = split ' ', $val;
  2529. my @v;
  2530. push @v, join('.', map { sprintf('%.2x',$_) } splice(@a,0,8)) while @a >= 8;
  2531. join ' ', @v;
  2532. },
  2533. # Note: Currently ignore the flags:
  2534. # byte 0 0x80 - color frame
  2535. # byte 0 0x40 - drop frame
  2536. # byte 1 0x80 - field phase
  2537. PrintConv => q{
  2538. my @a = map hex, split /[. ]+/, $val;
  2539. my @v;
  2540. while (@a >= 8) {
  2541. my $str = sprintf("%.2x:%.2x:%.2x.%.2x", $a[3]&0x3f,
  2542. $a[2]&0x7f, $a[1]&0x7f, $a[0]&0x3f);
  2543. if ($a[3] & 0x80) { # date+timezone exist if BGF2 is set
  2544. my $tz = $a[7] & 0x3f;
  2545. my $bz = sprintf('%.2x', $tz);
  2546. $bz = 100 if $bz =~ /[a-f]/i; # not BCD
  2547. if ($bz < 26) {
  2548. $tz = ($bz < 13 ? 0 : 26) - $bz;
  2549. } elsif ($bz == 32) {
  2550. $tz = 12.75;
  2551. } elsif ($bz >= 28 and $bz <= 31) {
  2552. $tz = 0; # UTC
  2553. } elsif ($bz < 100) {
  2554. undef $tz; # undefined or user-defined
  2555. } elsif ($tz < 0x20) {
  2556. $tz = (($tz < 0x10 ? 10 : 20) - $tz) - 0.5;
  2557. } else {
  2558. $tz = (($tz < 0x30 ? 53 : 63) - $tz) + 0.5;
  2559. }
  2560. if ($a[7] & 0x80) { # MJD format (/w UTC time)
  2561. my ($h,$m,$s,$f) = split /[:.]/, $str;
  2562. my $jday = sprintf('%x%.2x%.2x', reverse @a[4..6]);
  2563. $str = ConvertUnixTime(($jday - 40587) * 24 * 3600
  2564. + ((($h+$tz) * 60) + $m) * 60 + $s) . ".$f";
  2565. $str =~ s/^(\d+):(\d+):(\d+) /$1-$2-${3}T/;
  2566. } else { # YYMMDD (Note: CinemaDNG 1.1 example seems wrong)
  2567. my $yr = sprintf('%.2x',$a[6]) + 1900;
  2568. $yr += 100 if $yr < 1970;
  2569. $str = sprintf('%d-%.2x-%.2xT%s',$yr,$a[5],$a[4],$str);
  2570. }
  2571. $str .= TimeZoneString($tz*60) if defined $tz;
  2572. }
  2573. push @v, $str;
  2574. splice @a, 0, 8;
  2575. }
  2576. join ' ', @v;
  2577. },
  2578. },
  2579. 0xc764 => { #28
  2580. Name => 'FrameRate',
  2581. PrintConv => 'int($val * 1000 + 0.5) / 1000',
  2582. },
  2583. 0xc772 => { #28
  2584. Name => 'TStop',
  2585. PrintConv => 'join("-", map { sprintf("%.2f",$_) } split " ", $val)',
  2586. },
  2587. 0xc789 => 'ReelName', #28
  2588. 0xc791 => 'OriginalDefaultFinalSize', # DNG 1.4
  2589. 0xc792 => { # DNG 1.4
  2590. Name => 'OriginalBestQualitySize',
  2591. Notes => 'called OriginalBestQualityFinalSize by the DNG spec',
  2592. },
  2593. 0xc793 => 'OriginalDefaultCropSize', # DNG 1.4
  2594. 0xc7a1 => 'CameraLabel', #28
  2595. 0xc7a3 => { # DNG 1.4
  2596. Name => 'ProfileHueSatMapEncoding',
  2597. PrintConv => {
  2598. 0 => 'Linear',
  2599. 1 => 'sRGB',
  2600. },
  2601. },
  2602. 0xc7a4 => { # DNG 1.4
  2603. Name => 'ProfileLookTableEncoding',
  2604. PrintConv => {
  2605. 0 => 'Linear',
  2606. 1 => 'sRGB',
  2607. },
  2608. },
  2609. 0xc7a5 => 'BaselineExposureOffset', # DNG 1.4
  2610. 0xc7a6 => { # DNG 1.4
  2611. Name => 'DefaultBlackRender',
  2612. PrintConv => {
  2613. 0 => 'Auto',
  2614. 1 => 'None',
  2615. },
  2616. },
  2617. 0xc7a7 => { # DNG 1.4
  2618. Name => 'NewRawImageDigest',
  2619. Format => 'undef',
  2620. ValueConv => 'unpack("H*", $val)',
  2621. },
  2622. 0xc7a8 => 'RawToPreviewGain', # DNG 1.4
  2623. # 0xc7aa - undocumented DNG tag written by LR4 (int32u[1] - val=256, related to fast load data?)
  2624. 0xc7b5 => 'DefaultUserCrop', # DNG 1.4
  2625. 0xea1c => { #13
  2626. Name => 'Padding',
  2627. Binary => 1,
  2628. Writable => 'undef',
  2629. # must start with 0x1c 0xea by the WM Photo specification
  2630. # (not sure what should happen if padding is only 1 byte)
  2631. # (why does MicrosoftPhoto write "1c ea 00 00 00 08"?)
  2632. RawConvInv => '$val=~s/^../\x1c\xea/s; $val',
  2633. },
  2634. 0xea1d => {
  2635. Name => 'OffsetSchema',
  2636. Notes => "Microsoft's ill-conceived maker note offset difference",
  2637. # From the Microsoft documentation:
  2638. #
  2639. # Any time the "Maker Note" is relocated by Windows, the Exif MakerNote
  2640. # tag (37500) is updated automatically to reference the new location. In
  2641. # addition, Windows records the offset (or difference) between the old and
  2642. # new locations in the Exif OffsetSchema tag (59933). If the "Maker Note"
  2643. # contains relative references, the developer can add the value in
  2644. # OffsetSchema to the original references to find the correct information.
  2645. #
  2646. # My recommendation is for other developers to ignore this tag because the
  2647. # information it contains is unreliable. It will be wrong if the image has
  2648. # been subsequently edited by another application that doesn't recognize the
  2649. # new Microsoft tag.
  2650. #
  2651. # The new tag unfortunately only gives the difference between the new maker
  2652. # note offset and the original offset. Instead, it should have been designed
  2653. # to store the original offset. The new offset may change if the image is
  2654. # edited, which will invalidate the tag as currently written. If instead the
  2655. # original offset had been stored, the new difference could be easily
  2656. # calculated because the new maker note offset is known.
  2657. #
  2658. # I exchanged emails with a Microsoft technical representative, pointing out
  2659. # this problem shortly after they released the update (Feb 2007), but so far
  2660. # they have taken no steps to address this.
  2661. },
  2662. # 0xefee - int16u: 0 - seen this from a WIC-scanned image
  2663. # tags in the range 0xfde8-0xfe58 have been observed in PS7 files
  2664. # generated from RAW images. They are all strings with the
  2665. # tag name at the start of the string. To accomodate these types
  2666. # of tags, all tags with values above 0xf000 are handled specially
  2667. # by ProcessExif().
  2668. 0xfe00 => {
  2669. Name => 'KDC_IFD',
  2670. Groups => { 1 => 'KDC_IFD' },
  2671. Flags => 'SubIFD',
  2672. Notes => 'used in some Kodak KDC images',
  2673. SubDirectory => {
  2674. TagTable => 'Image::ExifTool::Kodak::KDC_IFD',
  2675. DirName => 'KDC_IFD',
  2676. Start => '$val',
  2677. },
  2678. },
  2679. );
  2680. # EXIF Composite tags (plus other more general Composite tags)
  2681. %Image::ExifTool::Exif::Composite = (
  2682. GROUPS => { 2 => 'Image' },
  2683. ImageSize => {
  2684. Require => {
  2685. 0 => 'ImageWidth',
  2686. 1 => 'ImageHeight',
  2687. },
  2688. Desire => {
  2689. 2 => 'ExifImageWidth',
  2690. 3 => 'ExifImageHeight',
  2691. },
  2692. # use ExifImageWidth/Height only for Canon and Phase One TIFF-base RAW images
  2693. ValueConv => q{
  2694. return "$val[2]x$val[3]" if $val[2] and $val[3] and
  2695. $$self{TIFF_TYPE} =~ /^(CR2|Canon 1D RAW|IIQ|EIP)$/;
  2696. return "$val[0]x$val[1]" if IsFloat($val[0]) and IsFloat($val[1]);
  2697. return undef;
  2698. },
  2699. },
  2700. Megapixels => {
  2701. Require => 'ImageSize',
  2702. ValueConv => 'my @d = ($val =~ /\d+/g); $d[0] * $d[1] / 1000000',
  2703. PrintConv => 'sprintf("%.*f", ($val >= 1 ? 1 : ($val >= 0.001 ? 3 : 6)), $val)',
  2704. },
  2705. # pick the best shutter speed value
  2706. ShutterSpeed => {
  2707. Desire => {
  2708. 0 => 'ExposureTime',
  2709. 1 => 'ShutterSpeedValue',
  2710. 2 => 'BulbDuration',
  2711. },
  2712. ValueConv => '($val[2] and $val[2]>0) ? $val[2] : (defined($val[0]) ? $val[0] : $val[1])',
  2713. PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
  2714. },
  2715. Aperture => {
  2716. Desire => {
  2717. 0 => 'FNumber',
  2718. 1 => 'ApertureValue',
  2719. },
  2720. RawConv => '($val[0] || $val[1]) ? $val : undef',
  2721. ValueConv => '$val[0] || $val[1]',
  2722. PrintConv => 'Image::ExifTool::Exif::PrintFNumber($val)',
  2723. },
  2724. LightValue => {
  2725. Notes => 'calculated LV -- similar to exposure value but normalized to ISO 100',
  2726. Require => {
  2727. 0 => 'Aperture',
  2728. 1 => 'ShutterSpeed',
  2729. 2 => 'ISO',
  2730. },
  2731. ValueConv => 'Image::ExifTool::Exif::CalculateLV($val[0],$val[1],$prt[2])',
  2732. PrintConv => 'sprintf("%.1f",$val)',
  2733. },
  2734. FocalLength35efl => { #26/PH
  2735. Description => 'Focal Length',
  2736. Notes => 'this value may be incorrect if the image has been resized',
  2737. Groups => { 2 => 'Camera' },
  2738. Require => {
  2739. 0 => 'FocalLength',
  2740. },
  2741. Desire => {
  2742. 1 => 'ScaleFactor35efl',
  2743. },
  2744. ValueConv => 'ToFloat(@val); ($val[0] || 0) * ($val[1] || 1)',
  2745. PrintConv => '$val[1] ? sprintf("%.1f mm (35 mm equivalent: %.1f mm)", $val[0], $val) : sprintf("%.1f mm", $val)',
  2746. },
  2747. ScaleFactor35efl => { #26/PH
  2748. Description => 'Scale Factor To 35 mm Equivalent',
  2749. Notes => q{
  2750. this value and any derived values may be incorrect if the image has been
  2751. resized
  2752. },
  2753. Groups => { 2 => 'Camera' },
  2754. Desire => {
  2755. 0 => 'FocalLength',
  2756. 1 => 'FocalLengthIn35mmFormat',
  2757. 2 => 'Composite:DigitalZoom',
  2758. 3 => 'FocalPlaneDiagonal',
  2759. 4 => 'SensorSize',
  2760. 5 => 'FocalPlaneXSize',
  2761. 6 => 'FocalPlaneYSize',
  2762. 7 => 'FocalPlaneResolutionUnit',
  2763. 8 => 'FocalPlaneXResolution',
  2764. 9 => 'FocalPlaneYResolution',
  2765. 10 => 'ExifImageWidth',
  2766. 11 => 'ExifImageHeight',
  2767. 12 => 'CanonImageWidth',
  2768. 13 => 'CanonImageHeight',
  2769. 14 => 'ImageWidth',
  2770. 15 => 'ImageHeight',
  2771. },
  2772. ValueConv => 'Image::ExifTool::Exif::CalcScaleFactor35efl($self, @val)',
  2773. PrintConv => 'sprintf("%.1f", $val)',
  2774. },
  2775. CircleOfConfusion => {
  2776. Notes => q{
  2777. calculated as D/1440, where D is the focal plane diagonal in mm. This value
  2778. may be incorrect if the image has been resized
  2779. },
  2780. Groups => { 2 => 'Camera' },
  2781. Require => 'ScaleFactor35efl',
  2782. ValueConv => 'sqrt(24*24+36*36) / ($val * 1440)',
  2783. PrintConv => 'sprintf("%.3f mm",$val)',
  2784. },
  2785. HyperfocalDistance => {
  2786. Notes => 'this value may be incorrect if the image has been resized',
  2787. Groups => { 2 => 'Camera' },
  2788. Require => {
  2789. 0 => 'FocalLength',
  2790. 1 => 'Aperture',
  2791. 2 => 'CircleOfConfusion',
  2792. },
  2793. ValueConv => q{
  2794. ToFloat(@val);
  2795. return 'inf' unless $val[1] and $val[2];
  2796. return $val[0] * $val[0] / ($val[1] * $val[2] * 1000);
  2797. },
  2798. PrintConv => 'sprintf("%.2f m", $val)',
  2799. },
  2800. DOF => {
  2801. Description => 'Depth Of Field',
  2802. Notes => 'this value may be incorrect if the image has been resized',
  2803. Require => {
  2804. 0 => 'FocalLength',
  2805. 1 => 'Aperture',
  2806. 2 => 'CircleOfConfusion',
  2807. },
  2808. Desire => {
  2809. 3 => 'FocusDistance', # focus distance in metres (0 is infinity)
  2810. 4 => 'SubjectDistance',
  2811. 5 => 'ObjectDistance',
  2812. 6 => 'ApproximateFocusDistance ',
  2813. 7 => 'FocusDistanceLower',
  2814. 8 => 'FocusDistanceUpper',
  2815. },
  2816. ValueConv => q{
  2817. ToFloat(@val);
  2818. my ($d, $f) = ($val[3], $val[0]);
  2819. if (defined $d) {
  2820. $d or $d = 1e10; # (use large number for infinity)
  2821. } else {
  2822. $d = $val[4] || $val[5] || $val[6];
  2823. unless (defined $d) {
  2824. return undef unless defined $val[7] and defined $val[8];
  2825. $d = ($val[7] + $val[8]) / 2;
  2826. }
  2827. }
  2828. return 0 unless $f and $val[2];
  2829. my $t = $val[1] * $val[2] * ($d * 1000 - $f) / ($f * $f);
  2830. my @v = ($d / (1 + $t), $d / (1 - $t));
  2831. $v[1] < 0 and $v[1] = 0; # 0 means 'inf'
  2832. return join(' ',@v);
  2833. },
  2834. PrintConv => q{
  2835. $val =~ tr/,/./; # in case locale is whacky
  2836. my @v = split ' ', $val;
  2837. $v[1] or return sprintf("inf (%.2f m - inf)", $v[0]);
  2838. my $dof = $v[1] - $v[0];
  2839. my $fmt = ($dof>0 and $dof<0.02) ? "%.3f" : "%.2f";
  2840. return sprintf("$fmt m ($fmt - $fmt m)",$dof,$v[0],$v[1]);
  2841. },
  2842. },
  2843. FOV => {
  2844. Description => 'Field Of View',
  2845. Notes => q{
  2846. calculated for the long image dimension. This value may be incorrect for
  2847. fisheye lenses, or if the image has been resized
  2848. },
  2849. Require => {
  2850. 0 => 'FocalLength',
  2851. 1 => 'ScaleFactor35efl',
  2852. },
  2853. Desire => {
  2854. 2 => 'FocusDistance', # (multiply by 1000 to convert to mm)
  2855. },
  2856. # ref http://www.bobatkins.com/photography/technical/field_of_view.html
  2857. # (calculations below apply to rectilinear lenses only, not fisheye)
  2858. ValueConv => q{
  2859. ToFloat(@val);
  2860. return undef unless $val[0] and $val[1];
  2861. my $corr = 1;
  2862. if ($val[2]) {
  2863. my $d = 1000 * $val[2] - $val[0];
  2864. $corr += $val[0]/$d if $d > 0;
  2865. }
  2866. my $fd2 = atan2(36, 2*$val[0]*$val[1]*$corr);
  2867. my @fov = ( $fd2 * 360 / 3.14159 );
  2868. if ($val[2] and $val[2] > 0 and $val[2] < 10000) {
  2869. push @fov, 2 * $val[2] * sin($fd2) / cos($fd2);
  2870. }
  2871. return join(' ', @fov);
  2872. },
  2873. PrintConv => q{
  2874. my @v = split(' ',$val);
  2875. my $str = sprintf("%.1f deg", $v[0]);
  2876. $str .= sprintf(" (%.2f m)", $v[1]) if $v[1];
  2877. return $str;
  2878. },
  2879. },
  2880. # generate DateTimeOriginal from Date and Time Created if not extracted already
  2881. DateTimeOriginal => {
  2882. Condition => 'not defined $$self{VALUE}{DateTimeOriginal}',
  2883. Description => 'Date/Time Original',
  2884. Groups => { 2 => 'Time' },
  2885. Desire => {
  2886. 0 => 'DateTimeCreated',
  2887. 1 => 'DateCreated',
  2888. 2 => 'TimeCreated',
  2889. },
  2890. RawConv => '($val[1] and $val[2]) ? $val : undef',
  2891. ValueConv => q{
  2892. return $val[0] if $val[0] and $val[0]=~/ /;
  2893. return "$val[1] $val[2]";
  2894. },
  2895. PrintConv => '$self->ConvertDateTime($val)',
  2896. },
  2897. ThumbnailImage => {
  2898. Groups => { 2 => 'Preview' },
  2899. Writable => 1,
  2900. WriteCheck => '$self->CheckImage(\$val)',
  2901. WriteAlso => {
  2902. # (the 0xfeedfeed values are translated in the Exif write routine)
  2903. ThumbnailOffset => 'defined $val ? 0xfeedfeed : undef',
  2904. ThumbnailLength => 'defined $val ? 0xfeedfeed : undef',
  2905. },
  2906. Require => {
  2907. 0 => 'ThumbnailOffset',
  2908. 1 => 'ThumbnailLength',
  2909. },
  2910. # retrieve the thumbnail from our EXIF data
  2911. RawConv => 'Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"ThumbnailImage")',
  2912. },
  2913. PreviewImage => {
  2914. Groups => { 2 => 'Preview' },
  2915. Writable => 1,
  2916. WriteCheck => '$self->CheckImage(\$val)',
  2917. DelCheck => '$val = ""; return undef', # can't delete, so set to empty string
  2918. WriteAlso => {
  2919. PreviewImageStart => 'defined $val ? 0xfeedfeed : undef',
  2920. PreviewImageLength => 'defined $val ? 0xfeedfeed : undef',
  2921. PreviewImageValid => 'defined $val and length $val ? 1 : 0',
  2922. },
  2923. Require => {
  2924. 0 => 'PreviewImageStart',
  2925. 1 => 'PreviewImageLength',
  2926. },
  2927. Desire => {
  2928. 2 => 'PreviewImageValid',
  2929. # (DNG and A100 ARW may be have 2 preview images)
  2930. 3 => 'PreviewImageStart (1)',
  2931. 4 => 'PreviewImageLength (1)',
  2932. },
  2933. # note: extract 2nd preview, but ignore double-referenced preview
  2934. # (in A100 ARW images, the 2nd PreviewImageLength from IFD0 may be wrong anyway)
  2935. RawConv => q{
  2936. if ($val[3] and $val[4] and $val[0] ne $val[3]) {
  2937. my %val = (
  2938. 0 => 'PreviewImageStart (1)',
  2939. 1 => 'PreviewImageLength (1)',
  2940. 2 => 'PreviewImageValid',
  2941. );
  2942. $self->FoundTag($tagInfo, \%val);
  2943. }
  2944. return undef if defined $val[2] and not $val[2];
  2945. return Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],'PreviewImage');
  2946. },
  2947. },
  2948. JpgFromRaw => {
  2949. Groups => { 2 => 'Preview' },
  2950. Writable => 1,
  2951. WriteCheck => '$self->CheckImage(\$val)',
  2952. WriteAlso => {
  2953. JpgFromRawStart => 'defined $val ? 0xfeedfeed : undef',
  2954. JpgFromRawLength => 'defined $val ? 0xfeedfeed : undef',
  2955. },
  2956. Require => {
  2957. 0 => 'JpgFromRawStart',
  2958. 1 => 'JpgFromRawLength',
  2959. },
  2960. RawConv => 'Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"JpgFromRaw")',
  2961. },
  2962. OtherImage => {
  2963. Groups => { 2 => 'Preview' },
  2964. Writable => 1,
  2965. WriteCheck => '$self->CheckImage(\$val)',
  2966. DelCheck => '$val = ""; return undef', # can't delete, so set to empty string
  2967. WriteAlso => {
  2968. OtherImageStart => 'defined $val ? 0xfeedfeed : undef',
  2969. OtherImageLength => 'defined $val ? 0xfeedfeed : undef',
  2970. },
  2971. Require => {
  2972. 0 => 'OtherImageStart',
  2973. 1 => 'OtherImageLength',
  2974. },
  2975. # retrieve the thumbnail from our EXIF data
  2976. RawConv => 'Image::ExifTool::Exif::ExtractImage($self,$val[0],$val[1],"OtherImage")',
  2977. },
  2978. PreviewImageSize => {
  2979. Require => {
  2980. 0 => 'PreviewImageWidth',
  2981. 1 => 'PreviewImageHeight',
  2982. },
  2983. ValueConv => '"$val[0]x$val[1]"',
  2984. },
  2985. SubSecDateTimeOriginal => {
  2986. Description => 'Date/Time Original',
  2987. Groups => { 2 => 'Time' },
  2988. Require => {
  2989. 0 => 'EXIF:DateTimeOriginal',
  2990. 1 => 'SubSecTimeOriginal',
  2991. },
  2992. # be careful here just in case there is a timezone following the seconds
  2993. RawConv => '$val[1]=~/\d/ ? $val : undef',
  2994. ValueConv => q{
  2995. $_ = $val[0]; s/( \d{2}:\d{2}:\d{2})/$1\.$val[1]/; $_;
  2996. },
  2997. PrintConv => '$self->ConvertDateTime($val)',
  2998. },
  2999. SubSecCreateDate => {
  3000. Description => 'Create Date',
  3001. Groups => { 2 => 'Time' },
  3002. Require => {
  3003. 0 => 'EXIF:CreateDate',
  3004. 1 => 'SubSecTimeDigitized',
  3005. },
  3006. RawConv => '$val[1]=~/\d/ ? $val : undef',
  3007. ValueConv => q{
  3008. $_ = $val[0]; s/( \d{2}:\d{2}:\d{2})/$1\.$val[1]/; $_;
  3009. },
  3010. PrintConv => '$self->ConvertDateTime($val)',
  3011. },
  3012. SubSecModifyDate => {
  3013. Description => 'Modify Date',
  3014. Groups => { 2 => 'Time' },
  3015. Require => {
  3016. 0 => 'EXIF:ModifyDate',
  3017. 1 => 'SubSecTime',
  3018. },
  3019. RawConv => '$val[1]=~/\d/ ? $val : undef',
  3020. ValueConv => q{
  3021. $_ = $val[0]; s/( \d{2}:\d{2}:\d{2})/$1\.$val[1]/; $_;
  3022. },
  3023. PrintConv => '$self->ConvertDateTime($val)',
  3024. },
  3025. CFAPattern => {
  3026. Require => {
  3027. 0 => 'CFARepeatPatternDim',
  3028. 1 => 'CFAPattern2',
  3029. },
  3030. # generate CFAPattern
  3031. ValueConv => q{
  3032. my @a = split / /, $val[0];
  3033. my @b = split / /, $val[1];
  3034. return '?' unless @a==2 and @b==$a[0]*$a[1];
  3035. return "$a[0] $a[1] @b";
  3036. },
  3037. PrintConv => 'Image::ExifTool::Exif::PrintCFAPattern($val)',
  3038. },
  3039. RedBalance => {
  3040. Groups => { 2 => 'Camera' },
  3041. Desire => {
  3042. 0 => 'WB_RGGBLevels',
  3043. 1 => 'WB_RGBGLevels',
  3044. 2 => 'WB_RBGGLevels',
  3045. 3 => 'WB_GRBGLevels',
  3046. 4 => 'WB_GRGBLevels',
  3047. 5 => 'WB_GBRGLevels',
  3048. 6 => 'WB_RGBLevels',
  3049. 7 => 'WB_GRBLevels',
  3050. 8 => 'WB_RBLevels',
  3051. 9 => 'WBRedLevel', # red
  3052. 10 => 'WBGreenLevel',
  3053. },
  3054. ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(0,@val)',
  3055. PrintConv => 'int($val * 1e6 + 0.5) * 1e-6',
  3056. },
  3057. BlueBalance => {
  3058. Groups => { 2 => 'Camera' },
  3059. Desire => {
  3060. 0 => 'WB_RGGBLevels',
  3061. 1 => 'WB_RGBGLevels',
  3062. 2 => 'WB_RBGGLevels',
  3063. 3 => 'WB_GRBGLevels',
  3064. 4 => 'WB_GRGBLevels',
  3065. 5 => 'WB_GBRGLevels',
  3066. 6 => 'WB_RGBLevels',
  3067. 7 => 'WB_GRBLevels',
  3068. 8 => 'WB_RBLevels',
  3069. 9 => 'WBBlueLevel', # blue
  3070. 10 => 'WBGreenLevel',
  3071. },
  3072. ValueConv => 'Image::ExifTool::Exif::RedBlueBalance(1,@val)',
  3073. PrintConv => 'int($val * 1e6 + 0.5) * 1e-6',
  3074. },
  3075. GPSPosition => {
  3076. Groups => { 2 => 'Location' },
  3077. Require => {
  3078. 0 => 'GPSLatitude',
  3079. 1 => 'GPSLongitude',
  3080. },
  3081. ValueConv => '"$val[0] $val[1]"',
  3082. PrintConv => '"$prt[0], $prt[1]"',
  3083. },
  3084. LensID => {
  3085. Groups => { 2 => 'Camera' },
  3086. Require => 'LensType',
  3087. Desire => {
  3088. 1 => 'FocalLength',
  3089. 2 => 'MaxAperture',
  3090. 3 => 'MaxApertureValue',
  3091. 4 => 'MinFocalLength',
  3092. 5 => 'MaxFocalLength',
  3093. 6 => 'LensModel',
  3094. 7 => 'LensFocalRange',
  3095. 8 => 'LensSpec',
  3096. 9 => 'LensType2',
  3097. 10 => 'LensFocalLength', # (for Pentax to check for converter)
  3098. },
  3099. Notes => q{
  3100. attempt to identify the actual lens from all lenses with a given LensType.
  3101. Applies only to LensType values with a lookup table. May be configured
  3102. by adding user-defined lenses
  3103. },
  3104. # this LensID is only valid if the LensType has a PrintConv or is a model name
  3105. RawConv => q{
  3106. my $printConv = $$self{TAG_INFO}{LensType}{PrintConv};
  3107. return $val if ref $printConv eq 'HASH' or (ref $printConv eq 'ARRAY' and
  3108. ref $$printConv[0] eq 'HASH') or $val[0] =~ /(mm|\d\/F)/;
  3109. return undef;
  3110. },
  3111. ValueConv => '$val',
  3112. PrintConv => q{
  3113. my $pcv;
  3114. # use LensType2 instead of LensType if available and valid (Sony E-mount lenses)
  3115. if ($val[9] and $val[9] & 0x8000) {
  3116. $val[0] = $val[9];
  3117. $prt[0] = $prt[9];
  3118. $pcv = $$self{TAG_INFO}{LensType2}{PrintConv};
  3119. }
  3120. my $lens = Image::ExifTool::Exif::PrintLensID($self, $prt[0], $pcv, $prt[8], @val);
  3121. # check for use of lens converter (Pentax K-3)
  3122. if ($val[10] and $val[1] and $lens) {
  3123. my $conv = $val[1] / $val[10];
  3124. $lens .= sprintf(' + %.1fx converter', $conv) if $conv > 1.1;
  3125. }
  3126. return $lens;
  3127. },
  3128. },
  3129. );
  3130. # table for unknown IFD entries
  3131. %Image::ExifTool::Exif::Unknown = (
  3132. GROUPS => { 0 => 'EXIF', 1 => 'UnknownIFD', 2 => 'Image'},
  3133. WRITE_PROC => \&WriteExif,
  3134. );
  3135. # add our composite tags
  3136. Image::ExifTool::AddCompositeTags('Image::ExifTool::Exif');
  3137. #------------------------------------------------------------------------------
  3138. # AutoLoad our writer routines when necessary
  3139. #
  3140. sub AUTOLOAD
  3141. {
  3142. return Image::ExifTool::DoAutoLoad($AUTOLOAD, @_);
  3143. }
  3144. #------------------------------------------------------------------------------
  3145. # Identify RAW file type for some TIFF-based formats using Compression value
  3146. # Inputs: 0) ExifTool object reference, 1) Compression value
  3147. # - sets TIFF_TYPE and FileType if identified
  3148. sub IdentifyRawFile($$)
  3149. {
  3150. my ($et, $comp) = @_;
  3151. if ($$et{FILE_TYPE} eq 'TIFF' and not $$et{IdentifiedRawFile}) {
  3152. if ($compression{$comp} and $compression{$comp} =~ /^\w+ ([A-Z]{3}) Compressed$/) {
  3153. $et->OverrideFileType($$et{TIFF_TYPE} = $1);
  3154. $$et{IdentifiedRawFile} = 1;
  3155. }
  3156. }
  3157. }
  3158. #------------------------------------------------------------------------------
  3159. # Calculate LV (Light Value)
  3160. # Inputs: 0) Aperture, 1) ShutterSpeed, 2) ISO
  3161. # Returns: LV value (and converts input values to floating point if necessary)
  3162. sub CalculateLV($$$)
  3163. {
  3164. local $_;
  3165. # do validity checks on arguments
  3166. return undef unless @_ >= 3;
  3167. foreach (@_) {
  3168. return undef unless $_ and /([+-]?(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?)/ and $1 > 0;
  3169. $_ = $1; # extract float from any other garbage
  3170. }
  3171. # (A light value of 0 is defined as f/1.0 at 1 second with ISO 100)
  3172. return (2*log($_[0]) - log($_[1]) - log($_[2]/100)) / log(2);
  3173. }
  3174. #------------------------------------------------------------------------------
  3175. # Calculate scale factor for 35mm effective focal length (ref 26/PH)
  3176. # Inputs: 0) ExifTool object ref
  3177. # 1) Focal length
  3178. # 2) Focal length in 35mm format
  3179. # 3) Canon digital zoom factor
  3180. # 4) Focal plane diagonal size (in mm)
  3181. # 5) Sensor size (X and Y in mm)
  3182. # 6/7) Focal plane X/Y size (in mm)
  3183. # 8) focal plane resolution units (1=None,2=inches,3=cm,4=mm,5=um)
  3184. # 9/10) Focal plane X/Y resolution
  3185. # 11/12,13/14...) Image width/height in order of precedence (first valid pair is used)
  3186. # Returns: 35mm conversion factor (or undefined if it can't be calculated)
  3187. sub CalcScaleFactor35efl
  3188. {
  3189. my $et = shift;
  3190. my $res = $_[7]; # save resolution units (in case they have been converted to string)
  3191. my $sensXY = $_[4];
  3192. Image::ExifTool::ToFloat(@_);
  3193. my $focal = shift;
  3194. my $foc35 = shift;
  3195. return $foc35 / $focal if $focal and $foc35;
  3196. my $digz = shift || 1;
  3197. my $diag = shift;
  3198. my $sens = shift;
  3199. # calculate Canon sensor size using a dedicated algorithm
  3200. if ($$et{Make} eq 'Canon') {
  3201. require Image::ExifTool::Canon;
  3202. my $canonDiag = Image::ExifTool::Canon::CalcSensorDiag(
  3203. $$et{RATIONAL}{FocalPlaneXResolution},
  3204. $$et{RATIONAL}{FocalPlaneYResolution},
  3205. );
  3206. $diag = $canonDiag if $canonDiag;
  3207. }
  3208. unless ($diag and Image::ExifTool::IsFloat($diag)) {
  3209. if ($sens and $sensXY =~ / (\d+(\.?\d*)?)$/) {
  3210. $diag = sqrt($sens * $sens + $1 * $1);
  3211. } else {
  3212. undef $diag;
  3213. my $xsize = shift;
  3214. my $ysize = shift;
  3215. if ($xsize and $ysize) {
  3216. # validate by checking aspect ratio because FocalPlaneX/YSize is not reliable
  3217. my $a = $xsize / $ysize;
  3218. if (abs($a-1.3333) < .1 or abs($a-1.5) < .1) {
  3219. $diag = sqrt($xsize * $xsize + $ysize * $ysize);
  3220. }
  3221. }
  3222. }
  3223. unless ($diag) {
  3224. # get number of mm in units (assume inches unless otherwise specified)
  3225. my %lkup = ( 3=>10, 4=>1, 5=>0.001 , cm=>10, mm=>1, um=>0.001 );
  3226. my $units = $lkup{ shift() || $res || '' } || 25.4;
  3227. my $x_res = shift || return undef;
  3228. my $y_res = shift || $x_res;
  3229. Image::ExifTool::IsFloat($x_res) and $x_res != 0 or return undef;
  3230. Image::ExifTool::IsFloat($y_res) and $y_res != 0 or return undef;
  3231. my ($w, $h);
  3232. for (;;) {
  3233. @_ < 2 and return undef;
  3234. $w = shift;
  3235. $h = shift;
  3236. next unless $w and $h;
  3237. my $a = $w / $h;
  3238. last if $a > 0.5 and $a < 2; # stop if we get a reasonable value
  3239. }
  3240. # calculate focal plane size in mm
  3241. $w *= $units / $x_res;
  3242. $h *= $units / $y_res;
  3243. $diag = sqrt($w*$w+$h*$h);
  3244. # make sure size is reasonable
  3245. return undef unless $diag > 1 and $diag < 100;
  3246. }
  3247. }
  3248. return sqrt(36*36+24*24) * $digz / $diag;
  3249. }
  3250. #------------------------------------------------------------------------------
  3251. # Print exposure compensation fraction
  3252. sub PrintFraction($)
  3253. {
  3254. my $val = shift;
  3255. my $str;
  3256. if (defined $val) {
  3257. $val *= 1.00001; # avoid round-off errors
  3258. if (not $val) {
  3259. $str = '0';
  3260. } elsif (int($val)/$val > 0.999) {
  3261. $str = sprintf("%+d", int($val));
  3262. } elsif ((int($val*2))/($val*2) > 0.999) {
  3263. $str = sprintf("%+d/2", int($val * 2));
  3264. } elsif ((int($val*3))/($val*3) > 0.999) {
  3265. $str = sprintf("%+d/3", int($val * 3));
  3266. } else {
  3267. $str = sprintf("%+.3g", $val);
  3268. }
  3269. }
  3270. return $str;
  3271. }
  3272. #------------------------------------------------------------------------------
  3273. # Convert fraction or number to floating point value (or 'undef' or 'inf')
  3274. sub ConvertFraction($)
  3275. {
  3276. my $val = shift;
  3277. if ($val =~ m{([-+]?\d+)/(\d+)}) {
  3278. $val = $2 ? $1 / $2 : ($1 ? 'inf' : 'undef');
  3279. }
  3280. return $val;
  3281. }
  3282. #------------------------------------------------------------------------------
  3283. # Convert EXIF text to something readable
  3284. # Inputs: 0) ExifTool object reference, 1) EXIF text,
  3285. # 2) [optional] 1 to apply CharsetEXIF to ASCII text,
  3286. # 3) tag name for warning message (may be argument 2)
  3287. # Returns: text encoded according to Charset option (with trailing spaces removed)
  3288. sub ConvertExifText($$;$$)
  3289. {
  3290. my ($et, $val, $asciiFlex, $tag) = @_;
  3291. return $val if length($val) < 8;
  3292. my $id = substr($val, 0, 8);
  3293. my $str = substr($val, 8);
  3294. # Note: allow spaces instead of nulls in the ID codes because
  3295. # it is fairly common for camera manufacturers to get this wrong
  3296. # (also handle Canon ZoomBrowser EX 4.5 null followed by 7 bytes of garbage)
  3297. if ($id =~ /^(ASCII)?(\0|[\0 ]+$)/) {
  3298. # truncate at null terminator (shouldn't have a null based on the
  3299. # EXIF spec, but it seems that few people actually read the spec)
  3300. $str =~ s/\0.*//s;
  3301. # allow ASCII text to contain any other specified encoding
  3302. if ($asciiFlex and $asciiFlex eq '1') {
  3303. my $enc = $et->Options('CharsetEXIF');
  3304. $str = $et->Decode($str, $enc) if $enc;
  3305. }
  3306. # by the EXIF spec, the following string should be "UNICODE\0", but
  3307. # apparently Kodak sometimes uses "Unicode\0" in the APP3 "Meta" information.
  3308. # However, unfortunately Ricoh uses "Unicode\0" in the RR30 EXIF UserComment
  3309. # when the text is actually ASCII, so only recognize uppercase "UNICODE\0".
  3310. } elsif ($id =~ /^UNICODE[\0 ]$/) {
  3311. # MicrosoftPhoto writes as little-endian even in big-endian EXIF,
  3312. # so we must guess at the true byte ordering
  3313. $str = $et->Decode($str, 'UTF16', 'Unknown');
  3314. } elsif ($id =~ /^JIS[\0 ]{5}$/) {
  3315. $str = $et->Decode($str, 'JIS', 'Unknown');
  3316. } else {
  3317. $tag = $asciiFlex if $asciiFlex and $asciiFlex ne 1;
  3318. $et->Warn('Invalid EXIF text encoding' . ($tag ? " for $tag" : ''));
  3319. $str = $id . $str;
  3320. }
  3321. $str =~ s/ +$//; # trim trailing blanks
  3322. return $str;
  3323. }
  3324. #------------------------------------------------------------------------------
  3325. # Print conversion for SpatialFrequencyResponse
  3326. sub PrintSFR($)
  3327. {
  3328. my $val = shift;
  3329. return $val unless length $val > 4;
  3330. my ($n, $m) = (Get16u(\$val, 0), Get16u(\$val, 2));
  3331. my @cols = split /\0/, substr($val, 4), $n+1;
  3332. my $pos = length($val) - 8 * $n * $m;
  3333. return $val unless @cols == $n+1 and $pos >= 4;
  3334. pop @cols;
  3335. my ($i, $j);
  3336. for ($i=0; $i<$n; ++$i) {
  3337. my @rows;
  3338. for ($j=0; $j<$m; ++$j) {
  3339. push @rows, Image::ExifTool::GetRational64u(\$val, $pos + 8*($i+$j*$n));
  3340. }
  3341. $cols[$i] .= '=' . join(',',@rows) . '';
  3342. }
  3343. return join '; ', @cols;
  3344. }
  3345. #------------------------------------------------------------------------------
  3346. # Print numerical parameter value (with sign, or 'Normal' for zero)
  3347. # Inputs: 0) value, 1) flag for inverse conversion, 2) conversion hash reference
  3348. sub PrintParameter($$$)
  3349. {
  3350. my ($val, $inv, $conv) = @_;
  3351. return $val if $inv;
  3352. if ($val > 0) {
  3353. if ($val > 0xfff0) { # a negative value in disguise?
  3354. $val = $val - 0x10000;
  3355. } else {
  3356. $val = "+$val";
  3357. }
  3358. }
  3359. return $val;
  3360. }
  3361. #------------------------------------------------------------------------------
  3362. # Convert parameter back to standard EXIF value
  3363. # 0,0.00,etc or "Normal" => 0
  3364. # -1,-2,etc or "Soft" or "Low" => 1
  3365. # +1,+2,1,2,etc or "Hard" or "High" => 2
  3366. sub ConvertParameter($)
  3367. {
  3368. my $val = shift;
  3369. my $isFloat = Image::ExifTool::IsFloat($val);
  3370. # normal is a value of zero
  3371. return 0 if $val =~ /\bn/i or ($isFloat and $val == 0);
  3372. # "soft", "low" or any negative number is a value of 1
  3373. return 1 if $val =~ /\b(s|l)/i or ($isFloat and $val < 0);
  3374. # "hard", "high" or any positive number is a value of 2
  3375. return 2 if $val =~ /\bh/i or $isFloat;
  3376. return undef;
  3377. }
  3378. #------------------------------------------------------------------------------
  3379. # Calculate Red/BlueBalance
  3380. # Inputs: 0) 0=red, 1=blue, 1-8) WB_RGGB/RGBG/RBGG/GRBG/GRGB/RGB/GRB/RBLevels,
  3381. # 8) red or blue level, 9) green level
  3382. my @rggbLookup = (
  3383. # indices for R, G, G and B components in input value
  3384. [ 0, 1, 2, 3 ], # 0 RGGB
  3385. [ 0, 1, 3, 2 ], # 1 RGBG
  3386. [ 0, 2, 3, 1 ], # 2 RBGG
  3387. [ 1, 0, 3, 2 ], # 3 GRBG
  3388. [ 1, 0, 2, 3 ], # 4 GRGB
  3389. [ 2, 3, 0, 1 ], # 5 GBRG
  3390. [ 0, 1, 1, 2 ], # 6 RGB
  3391. [ 1, 0, 0, 2 ], # 7 GRB
  3392. [ 0, 256, 256, 1 ], # 8 RB (green level is 256)
  3393. );
  3394. sub RedBlueBalance($@)
  3395. {
  3396. my $blue = shift;
  3397. my ($i, $val, $levels);
  3398. for ($i=0; $i<@rggbLookup; ++$i) {
  3399. $levels = shift or next;
  3400. my @levels = split ' ', $levels;
  3401. next if @levels < 2;
  3402. my $lookup = $rggbLookup[$i];
  3403. my $g = $$lookup[1]; # get green level or index
  3404. if ($g < 4) {
  3405. next if @levels < 3;
  3406. $g = ($levels[$g] + $levels[$$lookup[2]]) / 2 or next;
  3407. } elsif ($levels[$$lookup[$blue * 3]] < 4) {
  3408. $g = 1; # Some Nikon cameras use a scaling factor of 1 (E5700)
  3409. }
  3410. $val = $levels[$$lookup[$blue * 3]] / $g;
  3411. last;
  3412. }
  3413. $val = $_[0] / $_[1] if not defined $val and ($_[0] and $_[1]);
  3414. return $val;
  3415. }
  3416. #------------------------------------------------------------------------------
  3417. # Print exposure time as a fraction
  3418. sub PrintExposureTime($)
  3419. {
  3420. my $secs = shift;
  3421. if ($secs < 0.25001 and $secs > 0) {
  3422. return sprintf("1/%d",int(0.5 + 1/$secs));
  3423. }
  3424. $_ = sprintf("%.1f",$secs);
  3425. s/\.0$//;
  3426. return $_;
  3427. }
  3428. #------------------------------------------------------------------------------
  3429. # Print FNumber
  3430. sub PrintFNumber($)
  3431. {
  3432. my $val = shift;
  3433. if (Image::ExifTool::IsFloat($val) and $val > 0) {
  3434. # round to 1 decimal place, or 2 for values < 1.0
  3435. $val = sprintf(($val<1 ? "%.2f" : "%.1f"), $val);
  3436. }
  3437. return $val;
  3438. }
  3439. #------------------------------------------------------------------------------
  3440. # Decode raw CFAPattern value
  3441. # Inputs: 0) ExifTool ref, 1) binary value
  3442. # Returns: string of numbers
  3443. sub DecodeCFAPattern($$)
  3444. {
  3445. my ($self, $val) = @_;
  3446. # some panasonic cameras (SV-AS3, SV-AS30) write this in ascii (very odd)
  3447. if ($val =~ /^[0-6]+$/) {
  3448. $self->Warn('Incorrectly formatted CFAPattern', 1);
  3449. $val =~ tr/0-6/\x00-\x06/;
  3450. }
  3451. return $val unless length($val) >= 4;
  3452. my @a = unpack(GetByteOrder() eq 'II' ? 'v2C*' : 'n2C*', $val);
  3453. my $end = 2 + $a[0] * $a[1];
  3454. if ($end > @a) {
  3455. # try swapping byte order (I have seen this order different than in EXIF)
  3456. my ($x, $y) = unpack('n2',pack('v2',$a[0],$a[1]));
  3457. if (@a < 2 + $x * $y) {
  3458. $self->Warn('Invalid CFAPattern', 1);
  3459. } else {
  3460. ($a[0], $a[1]) = ($x, $y);
  3461. # (can't technically be wrong because the order isn't well defined by the EXIF spec)
  3462. # $self->Warn('Wrong byte order for CFAPattern');
  3463. }
  3464. }
  3465. return "@a";
  3466. }
  3467. #------------------------------------------------------------------------------
  3468. # Print CFA Pattern
  3469. sub PrintCFAPattern($)
  3470. {
  3471. my $val = shift;
  3472. my @a = split ' ', $val;
  3473. return '<truncated data>' unless @a >= 2;
  3474. return '<zero pattern size>' unless $a[0] and $a[1];
  3475. my $end = 2 + $a[0] * $a[1];
  3476. return '<invalid pattern size>' if $end > @a;
  3477. my @cfaColor = qw(Red Green Blue Cyan Magenta Yellow White);
  3478. my ($pos, $rtnVal) = (2, '[');
  3479. for (;;) {
  3480. $rtnVal .= $cfaColor[$a[$pos]] || 'Unknown';
  3481. last if ++$pos >= $end;
  3482. ($pos - 2) % $a[1] and $rtnVal .= ',', next;
  3483. $rtnVal .= '][';
  3484. }
  3485. return $rtnVal . ']';
  3486. }
  3487. #------------------------------------------------------------------------------
  3488. # Print conversion for lens info
  3489. # Inputs: 0) string of values (min focal, max focal, min F, max F)
  3490. # Returns: string in the form "12-20mm f/3.8-4.5" or "50mm f/1.4"
  3491. sub PrintLensInfo($)
  3492. {
  3493. my $val = shift;
  3494. my @vals = split ' ', $val;
  3495. return $val unless @vals == 4;
  3496. my $c = 0;
  3497. foreach (@vals) {
  3498. Image::ExifTool::IsFloat($_) and ++$c, next;
  3499. $_ eq 'inf' and $_ = '?', ++$c, next;
  3500. $_ eq 'undef' and $_ = '?', ++$c, next;
  3501. }
  3502. return $val unless $c == 4;
  3503. $val = $vals[0];
  3504. # (the Pentax Q writes zero for upper value of fixed-focal-length lenses)
  3505. $val .= "-$vals[1]" if $vals[1] and $vals[1] ne $vals[0];
  3506. $val .= "mm f/$vals[2]";
  3507. $val .= "-$vals[3]" if $vals[3] and $vals[3] ne $vals[2];
  3508. return $val;
  3509. }
  3510. #------------------------------------------------------------------------------
  3511. # Get lens info from lens model string
  3512. # Inputs: 0) lens string, 1) flag to allow unknown "?" values
  3513. # Returns: 0) min focal, 1) max focal, 2) min aperture, 3) max aperture
  3514. # Notes: returns empty list if lens string could not be parsed
  3515. sub GetLensInfo($;$)
  3516. {
  3517. my ($lens, $unk) = @_;
  3518. # extract focal length and aperture ranges for this lens
  3519. my $pat = '\\d+(?:\\.\\d+)?';
  3520. $pat .= '|\\?' if $unk;
  3521. return () unless $lens =~ /($pat)(?:-($pat))?\s*mm.*?(?:[fF]\/?\s*)($pat)(?:-($pat))?/;
  3522. # ($1=short focal, $2=long focal, $3=max aperture wide, $4=max aperture tele)
  3523. my @a = ($1, $2, $3, $4);
  3524. $a[1] or $a[1] = $a[0];
  3525. $a[3] or $a[3] = $a[2];
  3526. if ($unk) {
  3527. local $_;
  3528. $_ eq '?' and $_ = 'undef' foreach @a;
  3529. }
  3530. return @a;
  3531. }
  3532. #------------------------------------------------------------------------------
  3533. # Attempt to identify the specific lens if multiple lenses have the same LensType
  3534. # Inputs: 0) ExifTool object ref, 1) LensType print value, 2) PrintConv hash ref,
  3535. # 3) LensSpec print value, 4) LensType numerical value, 5) FocalLength,
  3536. # 6) MaxAperture, 7) MaxApertureValue, 8) MinFocalLength, 9) MaxFocalLength,
  3537. # 10) LensModel, 11) LensFocalRange, 12) LensSpec
  3538. sub PrintLensID($$@)
  3539. {
  3540. my ($et, $lensTypePrt, $printConv, $lensSpecPrt, $lensType, $focalLength,
  3541. $maxAperture, $maxApertureValue, $shortFocal, $longFocal, $lensModel,
  3542. $lensFocalRange, $lensSpec) = @_;
  3543. # this logic relies on the LensType lookup:
  3544. return undef unless defined $lensType;
  3545. # get print conversion hash if necessary
  3546. $printConv or $printConv = $$et{TAG_INFO}{LensType}{PrintConv};
  3547. # just copy LensType PrintConv value if it was a lens name
  3548. # (Olympus or Panasonic -- just exclude things like Nikon and Leaf LensType)
  3549. unless (ref $printConv eq 'HASH') {
  3550. if (ref $printConv eq 'ARRAY' and ref $$printConv[0] eq 'HASH') {
  3551. $printConv = $$printConv[0];
  3552. $lensTypePrt =~ s/;.*//;
  3553. $lensType =~ s/ .*//;
  3554. } else {
  3555. return $lensTypePrt if $lensTypePrt =~ /mm/;
  3556. return $lensTypePrt if $lensTypePrt =~ s/(\d)\/F/$1mm F/;
  3557. return undef;
  3558. }
  3559. }
  3560. # get LensSpec information if available (Sony)
  3561. my ($sf0, $lf0, $sa0, $la0);
  3562. if ($lensSpecPrt) {
  3563. ($sf0, $lf0, $sa0, $la0) = GetLensInfo($lensSpecPrt);
  3564. undef $sf0 unless $sa0; # (make sure aperture isn't zero)
  3565. }
  3566. # use MaxApertureValue if MaxAperture is not available
  3567. $maxAperture = $maxApertureValue unless $maxAperture;
  3568. if ($lensFocalRange and $lensFocalRange =~ /^(\d+)(?: (?:to )?(\d+))?$/) {
  3569. ($shortFocal, $longFocal) = ($1, $2 || $1);
  3570. }
  3571. if ($$et{Make} eq 'SONY') {
  3572. # patch for Metabones Canon adapters on Sony cameras (ref Jos Roost)
  3573. # (the Metabones adapters add 0xef00 or 0x7700 to the high byte
  3574. # for 2-byte LensType values, so we need to adjust for these)
  3575. if ($lensType != 0xffff) {
  3576. require Image::ExifTool::Minolta;
  3577. if ($Image::ExifTool::Minolta::metabonesID{$lensType & 0xff00}) {
  3578. $lensType -= ($lensType >= 0xef00 ? 0xef00 : $lensType >= 0xbc00 ? 0xbc00 : 0x7700);
  3579. require Image::ExifTool::Canon;
  3580. $printConv = \%Image::ExifTool::Canon::canonLensTypes;
  3581. $lensTypePrt = $$printConv{$lensType} if $$printConv{$lensType};
  3582. }
  3583. }
  3584. } elsif ($shortFocal and $longFocal) {
  3585. # Canon (and some other makes) include makernote information
  3586. # which allows better lens identification
  3587. require Image::ExifTool::Canon;
  3588. return Image::ExifTool::Canon::PrintLensID($printConv, $lensType,
  3589. $shortFocal, $longFocal, $maxAperture, $lensModel);
  3590. }
  3591. my $lens = $$printConv{$lensType};
  3592. return ($lensModel || $lensTypePrt) unless $lens;
  3593. return $lens unless $$printConv{"$lensType.1"};
  3594. $lens =~ s/ or .*//s; # remove everything after "or"
  3595. # make list of all possible matching lenses
  3596. my @lenses = ( $lens );
  3597. my $i;
  3598. for ($i=1; $$printConv{"$lensType.$i"}; ++$i) {
  3599. push @lenses, $$printConv{"$lensType.$i"};
  3600. }
  3601. # attempt to determine actual lens
  3602. my (@matches, @best, @user, $diff);
  3603. foreach $lens (@lenses) {
  3604. push @user, $lens if $Image::ExifTool::userLens{$lens};
  3605. # sf = short focal
  3606. # lf = long focal
  3607. # sa = max aperture at short focal
  3608. # la = max aperture at long focal
  3609. my ($sf, $lf, $sa, $la) = GetLensInfo($lens);
  3610. next unless $sf;
  3611. # check against LensSpec parameters if available
  3612. if ($sf0) {
  3613. next if abs($sf - $sf0) > 0.5 or abs($sa - $sa0) > 0.15 or
  3614. abs($lf - $lf0) > 0.5 or abs($la - $la0) > 0.15;
  3615. # the basic parameters match, but also check against additional lens features:
  3616. # for Sony A and E lenses, the full LensSpec string should match with end of LensType,
  3617. # excluding any part between () at the end, and preceded by a space (the space
  3618. # ensures that e.g. Zeiss Loxia 21mm having LensSpec "E 21mm F2.8" will not be
  3619. # identified as "Sony FE 21mm F2.8 (SEL28F20 + SEL075UWC)")
  3620. $lensSpecPrt and $lens =~ / \Q$lensSpecPrt\E( \(|$)/ and @best = ( $lens ), last;
  3621. # exactly-matching Sony lens should have been found above, so only add non-Sony lenses
  3622. push @best, $lens unless $lens =~ /^Sony /;
  3623. next;
  3624. }
  3625. # adjust focal length and aperture if teleconverter is attached (Minolta)
  3626. if ($lens =~ / \+ .*? (\d+(\.\d+)?)x( |$)/) {
  3627. $sf *= $1; $lf *= $1;
  3628. $sa *= $1; $la *= $1;
  3629. }
  3630. # see if we can rule out this lens using FocalLength and MaxAperture
  3631. if ($focalLength) {
  3632. next if $focalLength < $sf - 0.5;
  3633. next if $focalLength > $lf + 0.5;
  3634. }
  3635. if ($maxAperture) {
  3636. # it seems that most manufacturers set MaxAperture and MaxApertureValue
  3637. # to the maximum aperture (smallest F number) for the current focal length
  3638. # of the lens, so assume that MaxAperture varies with focal length and find
  3639. # the closest match (this is somewhat contrary to the EXIF specification which
  3640. # states "The smallest F number of the lens", without mention of focal length)
  3641. next if $maxAperture < $sa - 0.15; # (0.15 is arbitrary)
  3642. next if $maxAperture > $la + 0.15;
  3643. # now determine the best match for this aperture
  3644. my $aa; # approximate maximum aperture at this focal length
  3645. if ($sf == $lf or $sa == $la or $focalLength <= $sf) {
  3646. # either 1) prime lens, 2) fixed-aperture zoom, or 3) zoom at min focal
  3647. $aa = $sa;
  3648. } elsif ($focalLength >= $lf) {
  3649. $aa = $la;
  3650. } else {
  3651. # assume a log-log variation of max aperture with focal length
  3652. # (see http://regex.info/blog/2006-10-05/263)
  3653. $aa = exp(log($sa) + (log($la)-log($sa)) / (log($lf)-log($sf)) *
  3654. (log($focalLength)-log($sf)));
  3655. # a linear relationship between 1/FocalLength and 1/MaxAperture fits Sony better (ref 27)
  3656. #$aa = 1 / (1/$sa + (1/$focalLength - 1/$sf) * (1/$la - 1/$sa) / (1/$lf - 1/$sf));
  3657. }
  3658. my $d = abs($maxAperture - $aa);
  3659. if (defined $diff) {
  3660. $d > $diff + 0.15 and next; # (0.15 is arbitrary)
  3661. $d < $diff - 0.15 and undef @best;
  3662. }
  3663. $diff = $d;
  3664. push @best, $lens;
  3665. }
  3666. push @matches, $lens;
  3667. }
  3668. # return the user-defined lens if it exists
  3669. if (@user) {
  3670. # choose the best match if we have more than one
  3671. if (@user > 1) {
  3672. my ($try, @good);
  3673. foreach $try (\@best, \@matches) {
  3674. $Image::ExifTool::userLens{$_} and push @good, $_ foreach @$try;
  3675. return join(' or ', @good) if @good;
  3676. }
  3677. }
  3678. return join(' or ', @user);
  3679. }
  3680. # return the best match(es) from the possible lenses
  3681. return join(' or ', @best) if @best;
  3682. return join(' or ', @matches) if @matches;
  3683. $lens = $$printConv{$lensType};
  3684. return $lensModel if $lensModel and $lens =~ / or /; # (eg. Sony NEX-5N)
  3685. return $lens;
  3686. }
  3687. #------------------------------------------------------------------------------
  3688. # translate date into standard EXIF format
  3689. # Inputs: 0) date
  3690. # Returns: date in format '2003:10:22'
  3691. # - bad formats recognized: '2003-10-22','2003/10/22','2003 10 22','20031022'
  3692. # - removes null terminator if it exists
  3693. sub ExifDate($)
  3694. {
  3695. my $date = shift;
  3696. $date =~ s/\0$//; # remove any null terminator
  3697. # separate year:month:day with colons
  3698. # (have seen many other characters, including nulls, used erroneously)
  3699. $date =~ s/(\d{4})[^\d]*(\d{2})[^\d]*(\d{2})$/$1:$2:$3/;
  3700. return $date;
  3701. }
  3702. #------------------------------------------------------------------------------
  3703. # translate time into standard EXIF format
  3704. # Inputs: 0) time
  3705. # Returns: time in format '10:30:55'
  3706. # - bad formats recognized: '10 30 55', '103055', '103055+0500'
  3707. # - removes null terminator if it exists
  3708. # - leaves time zone intact if specified (eg. '10:30:55+05:00')
  3709. sub ExifTime($)
  3710. {
  3711. my $time = shift;
  3712. $time =~ tr/ /:/; # use ':' (not ' ') as a separator
  3713. $time =~ s/\0$//; # remove any null terminator
  3714. # add separators if they don't exist
  3715. $time =~ s/^(\d{2})(\d{2})(\d{2})/$1:$2:$3/;
  3716. $time =~ s/([+-]\d{2})(\d{2})\s*$/$1:$2/; # to timezone too
  3717. return $time;
  3718. }
  3719. #------------------------------------------------------------------------------
  3720. # extract image from file
  3721. # Inputs: 0) ExifTool object reference, 1) data offset (in file), 2) data length
  3722. # 3) [optional] tag name
  3723. # Returns: Reference to Image if specifically requested or "Binary data" message
  3724. # Returns undef if there was an error loading the image
  3725. sub ExtractImage($$$$)
  3726. {
  3727. my ($et, $offset, $len, $tag) = @_;
  3728. my $dataPt = \$$et{EXIF_DATA};
  3729. my $dataPos = $$et{EXIF_POS};
  3730. my $image;
  3731. # no image if length is zero, and don't try to extract binary from XMP file
  3732. return undef if not $len or $$et{FILE_TYPE} eq 'XMP';
  3733. # take data from EXIF block if possible
  3734. if (defined $dataPos and $offset>=$dataPos and $offset+$len<=$dataPos+length($$dataPt)) {
  3735. $image = substr($$dataPt, $offset-$dataPos, $len);
  3736. } else {
  3737. $image = $et->ExtractBinary($offset, $len, $tag);
  3738. return undef unless defined $image;
  3739. # patch for incorrect ThumbnailOffset in some Sony DSLR-A100 ARW images
  3740. if ($tag and $tag eq 'ThumbnailImage' and $$et{TIFF_TYPE} eq 'ARW' and
  3741. $$et{Model} eq 'DSLR-A100' and $offset < 0x10000 and
  3742. $image !~ /^(Binary data|\xff\xd8\xff)/)
  3743. {
  3744. my $try = $et->ExtractBinary($offset + 0x10000, $len, $tag);
  3745. if (defined $try and $try =~ /^\xff\xd8\xff/) {
  3746. $image = $try;
  3747. $$et{VALUE}{ThumbnailOffset} += 0x10000;
  3748. $et->Warn('Adjusted incorrect A100 ThumbnailOffset', 1);
  3749. }
  3750. }
  3751. }
  3752. return $et->ValidateImage(\$image, $tag);
  3753. }
  3754. #------------------------------------------------------------------------------
  3755. # Process EXIF directory
  3756. # Inputs: 0) ExifTool object reference
  3757. # 1) Reference to directory information hash
  3758. # 2) Pointer to tag table for this directory
  3759. # Returns: 1 on success, otherwise returns 0 and sets a Warning
  3760. sub ProcessExif($$$)
  3761. {
  3762. my ($et, $dirInfo, $tagTablePtr) = @_;
  3763. my $dataPt = $$dirInfo{DataPt};
  3764. my $dataPos = $$dirInfo{DataPos} || 0;
  3765. my $dataLen = $$dirInfo{DataLen};
  3766. my $dirStart = $$dirInfo{DirStart} || 0;
  3767. my $dirLen = $$dirInfo{DirLen} || $dataLen - $dirStart;
  3768. my $dirName = $$dirInfo{DirName};
  3769. my $base = $$dirInfo{Base} || 0;
  3770. my $firstBase = $base;
  3771. my $raf = $$dirInfo{RAF};
  3772. my $verbose = $et->Options('Verbose');
  3773. my $htmlDump = $$et{HTML_DUMP};
  3774. my $success = 1;
  3775. my ($tagKey, $dirSize, $makerAddr, $strEnc);
  3776. my $inMakerNotes = $$tagTablePtr{GROUPS}{0} eq 'MakerNotes';
  3777. # set encoding to assume for strings
  3778. $strEnc = $et->Options('CharsetEXIF') if $$tagTablePtr{GROUPS}{0} eq 'EXIF';
  3779. # ignore non-standard EXIF while in strict MWG compatibility mode
  3780. if ($Image::ExifTool::MWG::strict and $dirName eq 'IFD0' and
  3781. $tagTablePtr eq \%Image::ExifTool::Exif::Main and
  3782. $$et{FILE_TYPE} =~ /^(JPEG|TIFF|PSD)$/)
  3783. {
  3784. my $path = $et->MetadataPath();
  3785. unless ($path =~ /^(JPEG-APP1-IFD0|TIFF-IFD0|PSD-EXIFInfo-IFD0)$/) {
  3786. $et->Warn("Ignored non-standard EXIF at $path");
  3787. return 1;
  3788. }
  3789. }
  3790. $verbose = -1 if $htmlDump; # mix htmlDump into verbose so we can test for both at once
  3791. $dirName eq 'EXIF' and $dirName = $$dirInfo{DirName} = 'IFD0';
  3792. $$dirInfo{Multi} = 1 if $dirName =~ /^(IFD0|SubIFD)$/ and not defined $$dirInfo{Multi};
  3793. # get a more descriptive name for MakerNote sub-directories
  3794. my $name = $$dirInfo{Name};
  3795. $name = $dirName unless $name and $inMakerNotes and $name !~ /^MakerNote/;
  3796. my ($numEntries, $dirEnd);
  3797. if ($dirStart >= 0 and $dirStart <= $dataLen-2) {
  3798. # make sure data is large enough (patches bug in Olympus subdirectory lengths)
  3799. $numEntries = Get16u($dataPt, $dirStart);
  3800. $dirSize = 2 + 12 * $numEntries;
  3801. $dirEnd = $dirStart + $dirSize;
  3802. if ($dirSize > $dirLen) {
  3803. if ($verbose > 0 and not $$dirInfo{SubIFD}) {
  3804. my $short = $dirSize - $dirLen;
  3805. $$et{INDENT} =~ s/..$//; # keep indent the same
  3806. $et->Warn("Short directory size (missing $short bytes)");
  3807. $$et{INDENT} .= '| ';
  3808. }
  3809. undef $dirSize if $dirEnd > $dataLen; # read from file if necessary
  3810. }
  3811. }
  3812. # read IFD from file if necessary
  3813. unless ($dirSize) {
  3814. $success = 0;
  3815. if ($raf) {
  3816. # read the count of entries in this IFD
  3817. my $offset = $dirStart + $dataPos;
  3818. my ($buff, $buf2);
  3819. if ($raf->Seek($offset + $base, 0) and $raf->Read($buff,2) == 2) {
  3820. my $len = 12 * Get16u(\$buff,0);
  3821. # also read next IFD pointer if available
  3822. if ($raf->Read($buf2, $len+4) >= $len) {
  3823. $buff .= $buf2;
  3824. # make copy of dirInfo since we're going to modify it
  3825. my %newDirInfo = %$dirInfo;
  3826. $dirInfo = \%newDirInfo;
  3827. # update directory parameters for the newly loaded IFD
  3828. $dataPt = $$dirInfo{DataPt} = \$buff;
  3829. $dataPos = $$dirInfo{DataPos} = $offset;
  3830. $dataLen = $$dirInfo{DataLen} = length $buff;
  3831. $dirStart = $$dirInfo{DirStart} = 0;
  3832. $dirLen = $$dirInfo{DirLen} = length $buff;
  3833. $success = 1;
  3834. }
  3835. }
  3836. }
  3837. unless ($success) {
  3838. $et->Warn("Bad $name directory");
  3839. return 0;
  3840. }
  3841. $numEntries = Get16u($dataPt, $dirStart);
  3842. $dirSize = 2 + 12 * $numEntries;
  3843. $dirEnd = $dirStart + $dirSize;
  3844. }
  3845. $verbose > 0 and $et->VerboseDir($dirName, $numEntries);
  3846. my $bytesFromEnd = $dataLen - $dirEnd;
  3847. if ($bytesFromEnd < 4) {
  3848. unless ($bytesFromEnd==2 or $bytesFromEnd==0) {
  3849. $et->Warn("Illegal $name directory size ($numEntries entries)");
  3850. return 0;
  3851. }
  3852. }
  3853. # fix base offset for maker notes if necessary
  3854. if (defined $$dirInfo{MakerNoteAddr}) {
  3855. $makerAddr = $$dirInfo{MakerNoteAddr};
  3856. delete $$dirInfo{MakerNoteAddr};
  3857. if (Image::ExifTool::MakerNotes::FixBase($et, $dirInfo)) {
  3858. $base = $$dirInfo{Base};
  3859. $dataPos = $$dirInfo{DataPos};
  3860. }
  3861. }
  3862. if ($htmlDump) {
  3863. my $longName = $name eq 'MakerNotes' ? ($$dirInfo{Name} || $name) : $name;
  3864. if (defined $makerAddr) {
  3865. my $hdrLen = $dirStart + $dataPos + $base - $makerAddr;
  3866. $et->HDump($makerAddr, $hdrLen, "MakerNotes header", $longName) if $hdrLen > 0;
  3867. }
  3868. unless ($$dirInfo{NoDumpEntryCount}) {
  3869. $et->HDump($dirStart + $dataPos + $base, 2, "$longName entries",
  3870. "Entry count: $numEntries");
  3871. }
  3872. my $tip;
  3873. if ($bytesFromEnd >= 4) {
  3874. my $nxt = ($name =~ /^(.*?)(\d+)$/) ? $1 . ($2 + 1) : 'Next IFD';
  3875. $tip = sprintf("$nxt offset: 0x%.4x", Get32u($dataPt, $dirEnd));
  3876. }
  3877. $et->HDump($dirEnd + $dataPos + $base, 4, "Next IFD", $tip, 0);
  3878. }
  3879. # patch for Canon EOS 40D firmware 1.0.4 bug (incorrect directory counts)
  3880. # (must do this before parsing directory or CameraSettings offset will be suspicious)
  3881. if ($inMakerNotes and $$et{Model} eq 'Canon EOS 40D' and $numEntries) {
  3882. my $entry = $dirStart + 2 + 12 * ($numEntries - 1);
  3883. my $fmt = Get16u($dataPt, $entry + 2);
  3884. if ($fmt < 1 or $fmt > 13) {
  3885. $et->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]",
  3886. "Bad format type: $fmt", 1);
  3887. # adjust the number of directory entries
  3888. --$numEntries;
  3889. $dirEnd -= 12;
  3890. }
  3891. }
  3892. # loop through all entries in an EXIF directory (IFD)
  3893. my ($index, $valEnd, $offList, $offHash);
  3894. my ($warnCount, $lastID) = (0, -1);
  3895. for ($index=0; $index<$numEntries; ++$index) {
  3896. if ($warnCount > 10) {
  3897. $et->Warn("Too many warnings -- $name parsing aborted", 2) and return 0;
  3898. }
  3899. my $entry = $dirStart + 2 + 12 * $index;
  3900. my $tagID = Get16u($dataPt, $entry);
  3901. my $format = Get16u($dataPt, $entry+2);
  3902. my $count = Get32u($dataPt, $entry+4);
  3903. if ($format < 1 or $format > 13) {
  3904. $et->HDump($entry+$dataPos+$base,12,"[invalid IFD entry]",
  3905. "Bad format type: $format", 1);
  3906. # warn unless the IFD was just padded with zeros
  3907. if ($format) {
  3908. $et->Warn("Bad format ($format) for $name entry $index", $inMakerNotes);
  3909. ++$warnCount;
  3910. }
  3911. # assume corrupted IFD if this is our first entry (except Sony ILCE-7M2 firmware 1.21)
  3912. return 0 unless $index or $$et{Model} eq 'ILCE-7M2';
  3913. next;
  3914. }
  3915. my $formatStr = $formatName[$format]; # get name of this format
  3916. my $valueDataPt = $dataPt;
  3917. my $valueDataPos = $dataPos;
  3918. my $valueDataLen = $dataLen;
  3919. my $valuePtr = $entry + 8; # pointer to value within $$dataPt
  3920. my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID);
  3921. my ($origFormStr, $bad, $rational);
  3922. # hack to patch incorrect count in Kodak SubIFD3 tags
  3923. if ($count < 2 and ref $$tagTablePtr{$tagID} eq 'HASH' and $$tagTablePtr{$tagID}{FixCount}) {
  3924. $offList or ($offList, $offHash) = GetOffList($dataPt, $dirStart, $dataPos,
  3925. $numEntries, $tagTablePtr);
  3926. my $i = $$offHash{Get32u($dataPt, $valuePtr)};
  3927. if (defined $i and $i < $#$offList) {
  3928. my $oldCount = $count;
  3929. $count = int(($$offList[$i+1] - $$offList[$i]) / $formatSize[$format]);
  3930. $origFormStr = $formatName[$format] . '[' . $oldCount . ']' if $oldCount != $count;
  3931. }
  3932. }
  3933. my $size = $count * $formatSize[$format];
  3934. my $readSize = $size;
  3935. if ($size > 4) {
  3936. if ($size > 0x7fffffff) {
  3937. $et->Warn(sprintf("Invalid size (%u) for %s tag 0x%.4x", $size, $name, $tagID));
  3938. ++$warnCount;
  3939. next;
  3940. }
  3941. $valuePtr = Get32u($dataPt, $valuePtr);
  3942. # fix valuePtr if necessary
  3943. if ($$dirInfo{FixOffsets}) {
  3944. my $wFlag;
  3945. $valEnd or $valEnd = $dataPos + $dirEnd + 4;
  3946. #### eval FixOffsets ($valuePtr, $valEnd, $size, $tagID, $wFlag)
  3947. eval $$dirInfo{FixOffsets};
  3948. }
  3949. my $suspect;
  3950. # offset shouldn't point into TIFF header
  3951. $valuePtr < 8 and not $$dirInfo{ZeroOffsetOK} and $suspect = $warnCount;
  3952. # convert offset to pointer in $$dataPt
  3953. if ($$dirInfo{EntryBased} or (ref $$tagTablePtr{$tagID} eq 'HASH' and
  3954. $$tagTablePtr{$tagID}{EntryBased}))
  3955. {
  3956. $valuePtr += $entry;
  3957. } else {
  3958. $valuePtr -= $dataPos;
  3959. }
  3960. # value shouldn't overlap our directory
  3961. $suspect = $warnCount if $valuePtr < $dirEnd and $valuePtr+$size > $dirStart;
  3962. # load value from file if necessary
  3963. if ($valuePtr < 0 or $valuePtr+$size > $dataLen) {
  3964. # get value by seeking in file if we are allowed
  3965. my $buff;
  3966. if ($raf) {
  3967. # avoid loading large binary data unless necessary
  3968. # (eg. ImageSourceData -- layers in Photoshop TIFF image)
  3969. while ($size > BINARY_DATA_LIMIT) {
  3970. if ($tagInfo) {
  3971. # make large unknown blocks binary data
  3972. $$tagInfo{Binary} = 1 if $$tagInfo{Unknown};
  3973. last unless $$tagInfo{Binary}; # must read non-binary data
  3974. last if $$tagInfo{SubDirectory}; # must read SubDirectory data
  3975. my $lcTag = lc($$tagInfo{Name});
  3976. if ($$et{OPTIONS}{Binary} and
  3977. not $$et{EXCL_TAG_LOOKUP}{$lcTag})
  3978. {
  3979. # read binary data if specified unless tagsFromFile won't use it
  3980. last unless $$et{TAGS_FROM_FILE} and $$tagInfo{Protected};
  3981. }
  3982. # must read if tag is specified by name
  3983. last if $$et{REQ_TAG_LOOKUP}{$lcTag};
  3984. } else {
  3985. # must read value if needed for a condition
  3986. last if defined $tagInfo;
  3987. }
  3988. # (note: changing the value without changing $size will cause
  3989. # a warning in the verbose output, but we need to maintain the
  3990. # proper size for the htmlDump, so we can't change this)
  3991. $buff = "Binary data $size bytes";
  3992. $readSize = length $buff;
  3993. last;
  3994. }
  3995. # read from file if necessary
  3996. unless (defined $buff or
  3997. ($raf->Seek($base + $valuePtr + $dataPos,0) and
  3998. $raf->Read($buff,$size) == $size))
  3999. {
  4000. $et->Warn("Error reading value for $name entry $index", $inMakerNotes);
  4001. return 0 unless $inMakerNotes or $htmlDump;
  4002. ++$warnCount;
  4003. $buff = '' unless defined $buff;
  4004. $readSize = length $buff;
  4005. $bad = 1;
  4006. }
  4007. $valueDataLen = length $buff;
  4008. $valueDataPt = \$buff;
  4009. $valueDataPos = $valuePtr + $dataPos;
  4010. $valuePtr = 0;
  4011. } else {
  4012. my ($tagStr, $tmpInfo, $leicaTrailer);
  4013. if ($tagInfo) {
  4014. $tagStr = $$tagInfo{Name};
  4015. $leicaTrailer = $$tagInfo{LeicaTrailer};
  4016. } elsif (defined $tagInfo) {
  4017. $tmpInfo = $et->GetTagInfo($tagTablePtr, $tagID, \ '', $formatStr, $count);
  4018. if ($tmpInfo) {
  4019. $tagStr = $$tmpInfo{Name};
  4020. $leicaTrailer = $$tmpInfo{LeicaTrailer};
  4021. }
  4022. }
  4023. if ($tagInfo and $$tagInfo{ChangeBase}) {
  4024. # adjust base offset for this tag only
  4025. #### eval ChangeBase ($dirStart,$dataPos)
  4026. my $newBase = eval $$tagInfo{ChangeBase};
  4027. $valuePtr += $newBase;
  4028. }
  4029. $tagStr or $tagStr = sprintf("tag 0x%.4x",$tagID);
  4030. # allow PreviewImage to run outside EXIF data
  4031. if ($tagStr eq 'PreviewImage' and $$et{RAF}) {
  4032. my $pos = $$et{RAF}->Tell();
  4033. $buff = $et->ExtractBinary($base + $valuePtr + $dataPos, $size, 'PreviewImage');
  4034. $$et{RAF}->Seek($pos, 0);
  4035. $valueDataPt = \$buff;
  4036. $valueDataPos = $valuePtr + $dataPos;
  4037. $valueDataLen = $size;
  4038. $valuePtr = 0;
  4039. } elsif ($leicaTrailer and $$et{RAF}) {
  4040. if ($verbose > 0) {
  4041. $et->VPrint(0, "$$et{INDENT}$index) $tagStr --> (outside APP1 segment)\n");
  4042. }
  4043. if ($et->Options('FastScan')) {
  4044. $et->Warn('Ignored Leica MakerNote trailer');
  4045. } else {
  4046. require Image::ExifTool::Fixup;
  4047. $$et{LeicaTrailer} = {
  4048. TagInfo => $tagInfo || $tmpInfo,
  4049. Offset => $base + $valuePtr + $dataPos,
  4050. Size => $size,
  4051. Fixup => new Image::ExifTool::Fixup,
  4052. };
  4053. }
  4054. } else {
  4055. $et->Warn("Bad $name offset for $tagStr");
  4056. ++$warnCount;
  4057. }
  4058. unless (defined $buff) {
  4059. $valueDataPt = '';
  4060. $valueDataPos = $valuePtr + $dataPos;
  4061. $valueDataLen = 0;
  4062. $valuePtr = 0;
  4063. $bad = 1;
  4064. }
  4065. }
  4066. }
  4067. # warn about suspect offsets if they didn't already cause another warning
  4068. if (defined $suspect and $suspect == $warnCount) {
  4069. my $tagStr = $tagInfo ? $$tagInfo{Name} : sprintf('tag 0x%.4x', $tagID);
  4070. if ($et->Warn("Suspicious $name offset for $tagStr", $inMakerNotes)) {
  4071. ++$warnCount;
  4072. next unless $verbose;
  4073. }
  4074. }
  4075. }
  4076. # treat single unknown byte as int8u
  4077. $formatStr = 'int8u' if $format == 7 and $count == 1;
  4078. my ($val, $subdir, $wrongFormat);
  4079. if ($tagID > 0xf000 and $tagTablePtr eq \%Image::ExifTool::Exif::Main) {
  4080. my $oldInfo = $$tagTablePtr{$tagID};
  4081. if ((not $oldInfo or (ref $oldInfo eq 'HASH' and $$oldInfo{Condition} and
  4082. not $$oldInfo{PSRaw})) and not $bad)
  4083. {
  4084. # handle special case of Photoshop RAW tags (0xfde8-0xfe58)
  4085. # --> generate tags from the value if possible
  4086. $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize);
  4087. if (defined $val and $val =~ /(.*): (.*)/) {
  4088. my $tag = $1;
  4089. $val = $2;
  4090. $tag =~ s/'s//; # remove 's (so "Owner's Name" becomes "OwnerName")
  4091. $tag =~ tr/a-zA-Z0-9_//cd; # remove unknown characters
  4092. if ($tag) {
  4093. $tagInfo = {
  4094. Name => $tag,
  4095. Condition => '$$self{TIFF_TYPE} ne "DCR"',
  4096. ValueConv => '$_=$val;s/^.*: //;$_', # remove descr
  4097. PSRaw => 1, # (just as flag to avoid adding this again)
  4098. };
  4099. AddTagToTable($tagTablePtr, $tagID, $tagInfo);
  4100. # generate conditional list if a conditional tag already existed
  4101. $$tagTablePtr{$tagID} = [ $oldInfo, $tagInfo ] if $oldInfo;
  4102. }
  4103. }
  4104. }
  4105. }
  4106. if (defined $tagInfo and not $tagInfo) {
  4107. if ($bad) {
  4108. undef $tagInfo;
  4109. } else {
  4110. # GetTagInfo() required the value for a Condition
  4111. my $tmpVal = substr($$valueDataPt, $valuePtr, $readSize < 128 ? $readSize : 128);
  4112. # (use original format name in this call -- $formatStr may have been changed to int8u)
  4113. $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID, \$tmpVal,
  4114. $formatName[$format], $count);
  4115. }
  4116. }
  4117. # make sure we are handling the 'ifd' format properly
  4118. if (($format == 13 or $format == 18) and (not $tagInfo or not $$tagInfo{SubIFD})) {
  4119. my $str = sprintf('%s tag 0x%.4x IFD format not handled', $dirName, $tagID);
  4120. $et->Warn($str, $inMakerNotes);
  4121. }
  4122. if (defined $tagInfo) {
  4123. my $readFormat = $$tagInfo{Format};
  4124. $subdir = $$tagInfo{SubDirectory};
  4125. # unless otherwise specified, all SubDirectory data except
  4126. # EXIF SubIFD offsets should be unformatted
  4127. $readFormat = 'undef' if $subdir and not $$tagInfo{SubIFD} and not $readFormat;
  4128. # override EXIF format if specified
  4129. if ($readFormat) {
  4130. $formatStr = $readFormat;
  4131. my $newNum = $formatNumber{$formatStr};
  4132. if ($newNum and $newNum != $format) {
  4133. $origFormStr = $formatName[$format] . '[' . $count . ']';
  4134. $format = $newNum;
  4135. # adjust number of items for new format size
  4136. $count = int($size / $formatSize[$format]);
  4137. }
  4138. }
  4139. # verify that offset-type values are integral
  4140. if (($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) and not $intFormat{$formatStr}) {
  4141. $et->Warn("Wrong format ($formatStr) for $name $$tagInfo{Name}");
  4142. next unless $verbose;
  4143. $wrongFormat = 1;
  4144. }
  4145. } else {
  4146. next unless $verbose;
  4147. }
  4148. unless ($bad) {
  4149. # limit maximum length of data to reformat
  4150. # (avoids long delays when processing some corrupted files)
  4151. if ($count > 100000 and $formatStr !~ /^(undef|string|binary)$/) {
  4152. my $tagName = $tagInfo ? $$tagInfo{Name} : sprintf('tag 0x%.4x', $tagID);
  4153. if ($tagName ne 'TransferFunction' or $count ne 196608) {
  4154. my $minor = $count > 2000000 ? 0 : 2;
  4155. next if $et->Warn("Ignoring $dirName $tagName with excessive count", $minor);
  4156. }
  4157. }
  4158. # convert according to specified format
  4159. $val = ReadValue($valueDataPt,$valuePtr,$formatStr,$count,$readSize,\$rational);
  4160. # re-code if necessary
  4161. if ($strEnc and $formatStr eq 'string' and defined $val) {
  4162. $val = $et->Decode($val, $strEnc);
  4163. }
  4164. }
  4165. if ($verbose) {
  4166. my $tval = $val;
  4167. # also show as a rational
  4168. $tval .= " ($rational)" if defined $rational;
  4169. if ($htmlDump) {
  4170. my ($tagName, $colName);
  4171. if ($tagID == 0x927c and $dirName eq 'ExifIFD') {
  4172. $tagName = 'MakerNotes';
  4173. } elsif ($tagInfo) {
  4174. $tagName = $$tagInfo{Name};
  4175. } else {
  4176. $tagName = sprintf("Tag 0x%.4x",$tagID);
  4177. }
  4178. my $dname = sprintf("${name}-%.2d", $index);
  4179. # build our tool tip
  4180. $size < 0 and $size = $count * $formatSize[$format];
  4181. my $fstr = "$formatName[$format]\[$count]";
  4182. $fstr = "$origFormStr read as $fstr" if $origFormStr and $origFormStr ne $fstr;
  4183. $fstr .= ' <-- WRONG' if $wrongFormat;
  4184. my $tip = sprintf("Tag ID: 0x%.4x\n", $tagID) .
  4185. "Format: $fstr\nSize: $size bytes\n";
  4186. if ($size > 4) {
  4187. my $offPt = Get32u($dataPt,$entry+8);
  4188. my $actPt = $valuePtr + $valueDataPos + $base - ($$et{EXIF_POS} || 0);
  4189. $tip .= sprintf("Value offset: 0x%.4x\n", $offPt);
  4190. # highlight tag name (red for bad size)
  4191. my $style = ($bad or not defined $tval) ? 'V' : 'H';
  4192. if ($actPt != $offPt) {
  4193. $tip .= sprintf("Actual offset: 0x%.4x\n", $actPt);
  4194. my $sign = $actPt < $offPt ? '-' : '';
  4195. $tip .= sprintf("Offset base: ${sign}0x%.4x\n", abs($actPt - $offPt));
  4196. $style = 'F' if $style eq 'H'; # purple for different offsets
  4197. }
  4198. $colName = "<span class=$style>$tagName</span>";
  4199. $colName .= ' <span class=V>(odd)</span>' if $offPt & 0x01;
  4200. } else {
  4201. $colName = $tagName;
  4202. }
  4203. $colName .= ' <span class=V>(err)</span>' if $wrongFormat;
  4204. $colName .= ' <span class=V>(seq)</span>' if $tagID <= $lastID and not $inMakerNotes;
  4205. $lastID = $tagID;
  4206. if (not defined $tval) {
  4207. $tval = '<bad size/offset>';
  4208. } else {
  4209. $tval = substr($tval,0,28) . '[...]' if length($tval) > 32;
  4210. if ($formatStr =~ /^(string|undef|binary)/) {
  4211. # translate non-printable characters
  4212. $tval =~ tr/\x00-\x1f\x7f-\xff/./;
  4213. } elsif ($tagInfo and Image::ExifTool::IsInt($tval)) {
  4214. if ($$tagInfo{IsOffset} or $$tagInfo{SubIFD}) {
  4215. $tval = sprintf('0x%.4x', $tval);
  4216. my $actPt = $val + $base - ($$et{EXIF_POS} || 0);
  4217. if ($actPt != $val) {
  4218. $tval .= sprintf("\nActual offset: 0x%.4x", $actPt);
  4219. my $sign = $actPt < $val ? '-' : '';
  4220. $tval .= sprintf("\nOffset base: ${sign}0x%.4x", abs($actPt - $val));
  4221. }
  4222. } elsif ($$tagInfo{PrintHex}) {
  4223. $tval = sprintf('0x%x', $tval);
  4224. }
  4225. }
  4226. }
  4227. $tip .= "Value: $tval";
  4228. $et->HDump($entry+$dataPos+$base, 12, "$dname $colName", $tip, 1);
  4229. next if $valueDataLen < 0; # don't process bad pointer entry
  4230. if ($size > 4) {
  4231. my $exifDumpPos = $valuePtr + $valueDataPos + $base;
  4232. my $flag = 0;
  4233. if ($subdir) {
  4234. if ($$tagInfo{MakerNotes}) {
  4235. $flag = 0x04;
  4236. } elsif ($$tagInfo{NestedHtmlDump}) {
  4237. $flag = $$tagInfo{NestedHtmlDump} == 2 ? 0x10 : 0x04;
  4238. }
  4239. }
  4240. # add value data block (underlining maker notes data)
  4241. $et->HDump($exifDumpPos,$size,"$tagName value",'SAME', $flag);
  4242. }
  4243. } else {
  4244. if ($tagID <= $lastID and not $inMakerNotes) {
  4245. $et->Warn(sprintf('Tag ID 0x%.4x out of sequence in %s', $tagID, $dirName));
  4246. }
  4247. $lastID = $tagID;
  4248. my $fstr = $formatName[$format];
  4249. $fstr = "$origFormStr read as $fstr" if $origFormStr;
  4250. $et->VerboseInfo($tagID, $tagInfo,
  4251. Table => $tagTablePtr,
  4252. Index => $index,
  4253. Value => $tval,
  4254. DataPt => $valueDataPt,
  4255. DataPos => $valueDataPos + $base,
  4256. Size => $size,
  4257. Start => $valuePtr,
  4258. Format => $fstr,
  4259. Count => $count,
  4260. );
  4261. }
  4262. next if not $tagInfo or $wrongFormat;
  4263. }
  4264. next unless defined $val;
  4265. #..............................................................................
  4266. # Handle SubDirectory tag types
  4267. #
  4268. if ($subdir) {
  4269. # don't process empty subdirectories
  4270. unless ($size) {
  4271. unless ($$tagInfo{MakerNotes} or $inMakerNotes) {
  4272. $et->Warn("Empty $$tagInfo{Name} data", 1);
  4273. }
  4274. next;
  4275. }
  4276. my (@values, $newTagTable, $dirNum, $newByteOrder, $invalid);
  4277. my $tagStr = $$tagInfo{Name};
  4278. if ($$subdir{MaxSubdirs}) {
  4279. @values = split ' ', $val;
  4280. # limit the number of subdirectories we parse
  4281. my $over = @values - $$subdir{MaxSubdirs};
  4282. if ($over > 0) {
  4283. $et->Warn("Ignoring $over $tagStr directories");
  4284. splice @values, $$subdir{MaxSubdirs};
  4285. }
  4286. $val = shift @values;
  4287. }
  4288. if ($$subdir{TagTable}) {
  4289. $newTagTable = GetTagTable($$subdir{TagTable});
  4290. $newTagTable or warn("Unknown tag table $$subdir{TagTable}"), next;
  4291. } else {
  4292. $newTagTable = $tagTablePtr; # use existing table
  4293. }
  4294. # loop through all sub-directories specified by this tag
  4295. for ($dirNum=0; ; ++$dirNum) {
  4296. my $subdirBase = $base;
  4297. my $subdirDataPt = $valueDataPt;
  4298. my $subdirDataPos = $valueDataPos;
  4299. my $subdirDataLen = $valueDataLen;
  4300. my $subdirStart = $valuePtr;
  4301. if (defined $$subdir{Start}) {
  4302. # set local $valuePtr relative to file $base for eval
  4303. my $valuePtr = $subdirStart + $subdirDataPos;
  4304. #### eval Start ($valuePtr, $val)
  4305. my $newStart = eval($$subdir{Start});
  4306. unless (Image::ExifTool::IsInt($newStart)) {
  4307. $et->Warn("Bad value for $tagStr");
  4308. last;
  4309. }
  4310. # convert back to relative to $subdirDataPt
  4311. $newStart -= $subdirDataPos;
  4312. # adjust directory size if necessary
  4313. unless ($$tagInfo{SubIFD} or $$subdir{BadOffset}) {
  4314. $size -= $newStart - $subdirStart;
  4315. }
  4316. $subdirStart = $newStart;
  4317. }
  4318. # this is a pain, but some maker notes are always a specific
  4319. # byte order, regardless of the byte order of the file
  4320. my $oldByteOrder = GetByteOrder();
  4321. $newByteOrder = $$subdir{ByteOrder};
  4322. if ($newByteOrder) {
  4323. if ($newByteOrder =~ /^Little/i) {
  4324. $newByteOrder = 'II';
  4325. } elsif ($newByteOrder =~ /^Big/i) {
  4326. $newByteOrder = 'MM';
  4327. } elsif ($$subdir{OffsetPt}) {
  4328. undef $newByteOrder;
  4329. warn "Can't have variable byte ordering for SubDirectories using OffsetPt";
  4330. last;
  4331. } elsif ($subdirStart + 2 <= $subdirDataLen) {
  4332. # attempt to determine the byte ordering by checking
  4333. # at the number of directory entries. This is an int16u
  4334. # that should be a reasonable value.
  4335. my $num = Get16u($subdirDataPt, $subdirStart);
  4336. if ($num & 0xff00 and ($num>>8) > ($num&0xff)) {
  4337. # This looks wrong, we shouldn't have this many entries
  4338. my %otherOrder = ( II=>'MM', MM=>'II' );
  4339. $newByteOrder = $otherOrder{$oldByteOrder};
  4340. } else {
  4341. $newByteOrder = $oldByteOrder;
  4342. }
  4343. }
  4344. } else {
  4345. $newByteOrder = $oldByteOrder;
  4346. }
  4347. # set base offset if necessary
  4348. if ($$subdir{Base}) {
  4349. # calculate subdirectory start relative to $base for eval
  4350. my $start = $subdirStart + $subdirDataPos;
  4351. #### eval Base ($start,$base)
  4352. $subdirBase = eval($$subdir{Base}) + $base;
  4353. }
  4354. # add offset to the start of the directory if necessary
  4355. if ($$subdir{OffsetPt}) {
  4356. #### eval OffsetPt ($valuePtr)
  4357. my $pos = eval $$subdir{OffsetPt};
  4358. if ($pos + 4 > $subdirDataLen) {
  4359. $et->Warn("Bad $tagStr OffsetPt");
  4360. last;
  4361. }
  4362. SetByteOrder($newByteOrder);
  4363. $subdirStart += Get32u($subdirDataPt, $pos);
  4364. SetByteOrder($oldByteOrder);
  4365. }
  4366. if ($subdirStart < 0 or $subdirStart + 2 > $subdirDataLen) {
  4367. # convert $subdirStart back to a file offset
  4368. if ($raf) {
  4369. # reset SubDirectory buffer (we will load it later)
  4370. my $buff = '';
  4371. $subdirDataPt = \$buff;
  4372. $subdirDataLen = $size = length $buff;
  4373. } else {
  4374. my $msg = "Bad $tagStr SubDirectory start";
  4375. if ($verbose > 0) {
  4376. if ($subdirStart < 0) {
  4377. $msg .= " (directory start $subdirStart is before EXIF start)";
  4378. } else {
  4379. my $end = $subdirStart + $size;
  4380. $msg .= " (directory end is $end but EXIF size is only $subdirDataLen)";
  4381. }
  4382. }
  4383. $et->Warn($msg);
  4384. last;
  4385. }
  4386. }
  4387. # must update subdirDataPos if $base changes for this subdirectory
  4388. $subdirDataPos += $base - $subdirBase;
  4389. # build information hash for new directory
  4390. my %subdirInfo = (
  4391. Name => $tagStr,
  4392. Base => $subdirBase,
  4393. DataPt => $subdirDataPt,
  4394. DataPos => $subdirDataPos,
  4395. DataLen => $subdirDataLen,
  4396. DirStart => $subdirStart,
  4397. DirLen => $size,
  4398. RAF => $raf,
  4399. Parent => $dirName,
  4400. DirName => $$subdir{DirName},
  4401. FixBase => $$subdir{FixBase},
  4402. FixOffsets => $$subdir{FixOffsets},
  4403. EntryBased => $$subdir{EntryBased},
  4404. TagInfo => $tagInfo,
  4405. SubIFD => $$tagInfo{SubIFD},
  4406. Subdir => $subdir,
  4407. );
  4408. # (remember: some cameras incorrectly write maker notes in IFD0)
  4409. if ($$tagInfo{MakerNotes}) {
  4410. # don't parse makernotes if FastScan > 1
  4411. my $fast = $et->Options('FastScan');
  4412. last if $fast and $fast > 1;
  4413. $subdirInfo{MakerNoteAddr} = $valuePtr + $valueDataPos + $base;
  4414. $subdirInfo{NoFixBase} = 1 if defined $$subdir{Base};
  4415. }
  4416. # set directory IFD name from group name of family 1 if it exists,
  4417. # unless the tag is writable as a block in which case group 1 may
  4418. # have been set automatically
  4419. if ($$tagInfo{Groups} and not $$tagInfo{Writable}) {
  4420. $subdirInfo{DirName} = $$tagInfo{Groups}{1};
  4421. # number multiple subdirectories
  4422. $subdirInfo{DirName} =~ s/\d*$/$dirNum/ if $dirNum;
  4423. }
  4424. SetByteOrder($newByteOrder); # set byte order for this subdir
  4425. # validate the subdirectory if necessary
  4426. my $dirData = $subdirDataPt; # set data pointer to be used in eval
  4427. #### eval Validate ($val, $dirData, $subdirStart, $size)
  4428. my $ok = 0;
  4429. if (defined $$subdir{Validate} and not eval $$subdir{Validate}) {
  4430. $et->Warn("Invalid $tagStr data");
  4431. $invalid = 1;
  4432. } else {
  4433. if (not $subdirInfo{DirName} and $inMakerNotes) {
  4434. $subdirInfo{DirName} = $$tagInfo{Name};
  4435. }
  4436. # process the subdirectory
  4437. $ok = $et->ProcessDirectory(\%subdirInfo, $newTagTable, $$subdir{ProcessProc});
  4438. }
  4439. # print debugging information if there were errors
  4440. if (not $ok and $verbose > 1 and $subdirStart != $valuePtr) {
  4441. my $out = $et->Options('TextOut');
  4442. printf $out "%s (SubDirectory start = 0x%x)\n", $$et{INDENT}, $subdirStart;
  4443. }
  4444. SetByteOrder($oldByteOrder); # restore original byte swapping
  4445. @values or last;
  4446. $val = shift @values; # continue with next subdir
  4447. }
  4448. my $doMaker = $et->Options('MakerNotes');
  4449. next unless $doMaker or $$et{REQ_TAG_LOOKUP}{lc($tagStr)} or $$tagInfo{BlockExtract};
  4450. # extract as a block if specified
  4451. if ($$tagInfo{MakerNotes}) {
  4452. # save maker note byte order (if it was significant and valid)
  4453. if ($$subdir{ByteOrder} and not $invalid) {
  4454. $$et{MAKER_NOTE_BYTE_ORDER} =
  4455. defined ($$et{UnknownByteOrder}) ?
  4456. $$et{UnknownByteOrder} : $newByteOrder;
  4457. }
  4458. if ($doMaker and $doMaker eq '2') {
  4459. # extract maker notes without rebuilding (no fixup information)
  4460. delete $$et{MAKER_NOTE_FIXUP};
  4461. } elsif (not $$tagInfo{NotIFD}) {
  4462. # this is a pain, but we must rebuild EXIF-typemaker notes to
  4463. # include all the value data if data was outside the maker notes
  4464. my %makerDirInfo = (
  4465. Name => $tagStr,
  4466. Base => $base,
  4467. DataPt => $valueDataPt,
  4468. DataPos => $valueDataPos,
  4469. DataLen => $valueDataLen,
  4470. DirStart => $valuePtr,
  4471. DirLen => $size,
  4472. RAF => $raf,
  4473. Parent => $dirName,
  4474. DirName => 'MakerNotes',
  4475. FixOffsets => $$subdir{FixOffsets},
  4476. TagInfo => $tagInfo,
  4477. );
  4478. $makerDirInfo{FixBase} = 1 if $$subdir{FixBase};
  4479. # rebuild maker notes (creates $$et{MAKER_NOTE_FIXUP})
  4480. my $val2 = RebuildMakerNotes($et, $newTagTable, \%makerDirInfo);
  4481. if (defined $val2) {
  4482. $val = $val2;
  4483. } elsif ($size > 4) {
  4484. $et->Warn('Error rebuilding maker notes (may be corrupt)');
  4485. }
  4486. }
  4487. } else {
  4488. # extract this directory as a block if specified
  4489. next unless $$tagInfo{Writable};
  4490. }
  4491. }
  4492. #..............................................................................
  4493. # convert to absolute offsets if this tag is an offset
  4494. #### eval IsOffset ($val, $et)
  4495. if ($$tagInfo{IsOffset} and eval $$tagInfo{IsOffset}) {
  4496. my $offsetBase = $$tagInfo{IsOffset} eq '2' ? $firstBase : $base;
  4497. $offsetBase += $$et{BASE};
  4498. # handle offsets which use a wrong base (Minolta A200)
  4499. if ($$tagInfo{WrongBase}) {
  4500. my $self = $et;
  4501. #### eval WrongBase ($self)
  4502. $offsetBase += eval $$tagInfo{WrongBase} || 0;
  4503. }
  4504. my @vals = split(' ',$val);
  4505. foreach $val (@vals) {
  4506. $val += $offsetBase;
  4507. }
  4508. $val = join(' ', @vals);
  4509. }
  4510. # save the value of this tag
  4511. $tagKey = $et->FoundTag($tagInfo, $val);
  4512. if (defined $tagKey) {
  4513. # set the group 1 name for tags in specified tables
  4514. $et->SetGroup($tagKey, $dirName) if $$tagTablePtr{SET_GROUP1};
  4515. # save original components of rational numbers (used when copying)
  4516. $$et{RATIONAL}{$tagKey} = $rational if defined $rational;
  4517. }
  4518. }
  4519. # scan for subsequent IFD's if specified
  4520. if ($$dirInfo{Multi} and $bytesFromEnd >= 4) {
  4521. my $offset = Get32u($dataPt, $dirEnd);
  4522. if ($offset) {
  4523. my $subdirStart = $offset - $dataPos;
  4524. # use same directory information for trailing directory,
  4525. # but change the start location (ProcessDirectory will
  4526. # test to make sure we don't reprocess the same dir twice)
  4527. my %newDirInfo = %$dirInfo;
  4528. $newDirInfo{DirStart} = $subdirStart;
  4529. # increment IFD number
  4530. my $ifdNum = $newDirInfo{DirName} =~ s/(\d+)$// ? $1 : 0;
  4531. $newDirInfo{DirName} .= $ifdNum + 1;
  4532. # must validate SubIFD1 because the nextIFD pointer is invalid for some RAW formats
  4533. if ($newDirInfo{DirName} ne 'SubIFD1' or ValidateIFD(\%newDirInfo)) {
  4534. $$et{INDENT} =~ s/..$//; # keep indent the same
  4535. my $cur = pop @{$$et{PATH}};
  4536. $et->ProcessDirectory(\%newDirInfo, $tagTablePtr) or $success = 0;
  4537. push @{$$et{PATH}}, $cur;
  4538. } elsif ($verbose or $$et{TIFF_TYPE} eq 'TIFF') {
  4539. $et->Warn('Ignored bad IFD linked from SubIFD');
  4540. }
  4541. }
  4542. }
  4543. return $success;
  4544. }
  4545. 1; # end
  4546. __END__
  4547. =head1 NAME
  4548. Image::ExifTool::Exif - Read EXIF/TIFF meta information
  4549. =head1 SYNOPSIS
  4550. This module is required by Image::ExifTool.
  4551. =head1 DESCRIPTION
  4552. This module contains routines required by Image::ExifTool for processing
  4553. EXIF and TIFF meta information.
  4554. =head1 AUTHOR
  4555. Copyright 2003-2016, Phil Harvey (phil at owl.phy.queensu.ca)
  4556. This library is free software; you can redistribute it and/or modify it
  4557. under the same terms as Perl itself.
  4558. =head1 REFERENCES
  4559. =over 4
  4560. =item L<http://www.exif.org/Exif2-2.PDF>
  4561. =item L<http://www.cipa.jp/std/documents/e/DC-008-2012_E.pdf>
  4562. =item L<http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf>
  4563. =item L<http://partners.adobe.com/public/developer/en/tiff/TIFFPM6.pdf>
  4564. =item L<http://www.adobe.com/products/dng/pdfs/dng_spec.pdf>
  4565. =item L<http://www.awaresystems.be/imaging/tiff/tifftags.html>
  4566. =item L<http://www.remotesensing.org/libtiff/TIFFTechNote2.html>
  4567. =item L<http://www.exif.org/dcf.PDF>
  4568. =item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html>
  4569. =item L<http://www.fine-view.com/jp/lab/doc/ps6ffspecsv2.pdf>
  4570. =item L<http://www.ozhiker.com/electronics/pjmt/jpeg_info/meta.html>
  4571. =item L<http://hul.harvard.edu/jhove/tiff-tags.html>
  4572. =item L<http://www.microsoft.com/whdc/xps/wmphoto.mspx>
  4573. =item L<http://www.asmail.be/msg0054681802.html>
  4574. =item L<http://crousseau.free.fr/imgfmt_raw.htm>
  4575. =item L<http://www.cybercom.net/~dcoffin/dcraw/>
  4576. =item L<http://www.digitalpreservation.gov/formats/content/tiff_tags.shtml>
  4577. =item L<http://community.roxen.com/developers/idocs/rfc/rfc3949.html>
  4578. =item L<http://tools.ietf.org/html/draft-ietf-fax-tiff-fx-extension1-01>
  4579. =item L<http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/cinemadng/pdfs/CinemaDNG_Format_Specification_v1_1.pdf>
  4580. =back
  4581. =head1 ACKNOWLEDGEMENTS
  4582. Thanks to Jeremy Brown for the 35efl tags, and Matt Madrid for his help with
  4583. the XP character code conversions.
  4584. =head1 SEE ALSO
  4585. L<Image::ExifTool::TagNames/EXIF Tags>,
  4586. L<Image::ExifTool(3pm)|Image::ExifTool>
  4587. =cut