MakerNotes.pm 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735
  1. #------------------------------------------------------------------------------
  2. # File: MakerNotes.pm
  3. #
  4. # Description: Read and write EXIF maker notes
  5. #
  6. # Revisions: 11/11/2004 - P. Harvey Created
  7. #------------------------------------------------------------------------------
  8. package Image::ExifTool::MakerNotes;
  9. use strict;
  10. use vars qw($VERSION);
  11. use Image::ExifTool qw(:DataAccess);
  12. use Image::ExifTool::Exif;
  13. sub ProcessUnknown($$$);
  14. sub ProcessUnknownOrPreview($$$);
  15. sub ProcessCanon($$$);
  16. sub ProcessGE2($$$);
  17. sub ProcessKodakPatch($$$);
  18. sub WriteUnknownOrPreview($$$);
  19. sub FixLeicaBase($$;$);
  20. $VERSION = '1.97';
  21. my $debug; # set to 1 to enable debugging code
  22. # conditional list of maker notes
  23. # Notes:
  24. # - This is NOT a normal tag table!
  25. # - All byte orders are now specified because we can now
  26. # write maker notes into a file with different byte ordering!
  27. # - Put these in alphabetical order to make TagNames documentation nicer.
  28. @Image::ExifTool::MakerNotes::Main = (
  29. # decide which MakerNotes to use (based on camera make/model)
  30. {
  31. Name => 'MakerNoteApple',
  32. Condition => '$$valPt =~ /^Apple iOS\0/',
  33. SubDirectory => {
  34. TagTable => 'Image::ExifTool::Apple::Main',
  35. ByteOrder => 'Unknown',
  36. Start => '$valuePtr + 14',
  37. Base => '$start - 14',
  38. },
  39. },
  40. {
  41. # this maker notes starts with a standard TIFF header at offset 0x0a
  42. # (must check Nikon signature first because Nikon Capture NX can generate
  43. # NEF images containing Nikon maker notes from JPEG images of any camera model)
  44. Name => 'MakerNoteNikon',
  45. Condition => '$$valPt=~/^Nikon\x00\x02/',
  46. SubDirectory => {
  47. TagTable => 'Image::ExifTool::Nikon::Main',
  48. Start => '$valuePtr + 18',
  49. Base => '$start - 8',
  50. ByteOrder => 'Unknown',
  51. },
  52. },
  53. {
  54. Name => 'MakerNoteCanon',
  55. # (starts with an IFD)
  56. Condition => '$$self{Make} =~ /^Canon/',
  57. SubDirectory => {
  58. TagTable => 'Image::ExifTool::Canon::Main',
  59. ProcessProc => \&ProcessCanon,
  60. ByteOrder => 'Unknown',
  61. },
  62. },
  63. {
  64. Name => 'MakerNoteCasio',
  65. # do negative lookahead assertion just to get tags
  66. # in a nice order for documentation
  67. # (starts with an IFD)
  68. Condition => '$$self{Make}=~/^CASIO/ and $$valPt!~/^(QVC|DCI)\0/',
  69. SubDirectory => {
  70. TagTable => 'Image::ExifTool::Casio::Main',
  71. ByteOrder => 'Unknown',
  72. },
  73. },
  74. {
  75. Name => 'MakerNoteCasio2',
  76. # (starts with "QVC\0" [Casio] or "DCI\0" [Concord])
  77. # (also found in AVI and MOV videos)
  78. Condition => '$$valPt =~ /^(QVC|DCI)\0/',
  79. SubDirectory => {
  80. TagTable => 'Image::ExifTool::Casio::Type2',
  81. Start => '$valuePtr + 6',
  82. ByteOrder => 'Unknown',
  83. FixBase => 1, # necessary for AVI and MOV videos
  84. },
  85. },
  86. {
  87. Name => 'MakerNoteFLIR',
  88. # (starts with IFD, Make is 'FLIR Systems AB' or 'FLIR Systems')
  89. Condition => '$$self{Make} =~ /^FLIR Systems/',
  90. SubDirectory => {
  91. TagTable => 'Image::ExifTool::FLIR::Main',
  92. Start => '$valuePtr',
  93. ByteOrder => 'Unknown',
  94. },
  95. },
  96. {
  97. # The Fuji maker notes use a structure similar to a self-contained
  98. # TIFF file, but with "FUJIFILM" instead of the standard TIFF header
  99. Name => 'MakerNoteFujiFilm',
  100. # (starts with "FUJIFILM" -- also used by some Leica, Minolta and Sharp models)
  101. # (GE FujiFilm models start with "GENERALE")
  102. Condition => '$$valPt =~ /^(FUJIFILM|GENERALE)/',
  103. SubDirectory => {
  104. TagTable => 'Image::ExifTool::FujiFilm::Main',
  105. # there is an 8-byte maker tag (FUJIFILM) we must skip over
  106. OffsetPt => '$valuePtr+8',
  107. # the pointers are relative to the subdirectory start
  108. # (before adding the offsetPt) - PH
  109. Base => '$start',
  110. ByteOrder => 'LittleEndian',
  111. },
  112. },
  113. {
  114. Name => 'MakerNoteGE',
  115. Condition => '$$valPt =~ /^GE(\0\0|NIC\0)/',
  116. SubDirectory => {
  117. TagTable => 'Image::ExifTool::GE::Main',
  118. Start => '$valuePtr + 18',
  119. FixBase => 1,
  120. AutoFix => 1,
  121. ByteOrder => 'Unknown',
  122. },
  123. },
  124. {
  125. Name => 'MakerNoteGE2',
  126. Condition => '$$valPt =~ /^GE\x0c\0\0\0\x16\0\0\0/',
  127. # Note: we will get a "Maker notes could not be parsed" warning when writing
  128. # these maker notes because they aren't currently supported for writing
  129. SubDirectory => {
  130. TagTable => 'Image::ExifTool::FujiFilm::Main',
  131. ProcessProc => \&ProcessGE2,
  132. Start => '$valuePtr + 12',
  133. Base => '$start - 6',
  134. ByteOrder => 'LittleEndian',
  135. # hard patch for crazy offsets
  136. FixOffsets => '$valuePtr -= 210 if $tagID >= 0x1303',
  137. },
  138. },
  139. {
  140. Name => 'MakerNoteHasselblad',
  141. Condition => '$$self{Make} eq "Hasselblad"',
  142. SubDirectory => {
  143. TagTable => 'Image::ExifTool::Unknown::Main',
  144. ByteOrder => 'Unknown',
  145. Start => '$valuePtr',
  146. Base => 0, # (avoids warnings since maker notes are not self-contained)
  147. },
  148. },
  149. # (the GE X5 has really messed up EXIF-like maker notes starting with
  150. # "GENIC\x0c\0" --> currently not decoded)
  151. {
  152. Name => 'MakerNoteHP', # PhotoSmart 720 (also Vivitar 3705, 3705B and 3715)
  153. Condition => '$$valPt =~ /^(Hewlett-Packard|Vivitar)/',
  154. SubDirectory => {
  155. TagTable => 'Image::ExifTool::HP::Main',
  156. ProcessProc => \&ProcessUnknown,
  157. ByteOrder => 'Unknown',
  158. },
  159. },
  160. {
  161. Name => 'MakerNoteHP2', # PhotoSmart E427
  162. # (this type of maker note also used by BenQ, Mustek, Sanyo, Traveler and Vivitar)
  163. Condition => '$$valPt =~ /^610[\0-\4]/',
  164. NotIFD => 1,
  165. SubDirectory => {
  166. TagTable => 'Image::ExifTool::HP::Type2',
  167. Start => '$valuePtr',
  168. ByteOrder => 'LittleEndian',
  169. },
  170. },
  171. {
  172. Name => 'MakerNoteHP4', # PhotoSmart M627
  173. Condition => '$$valPt =~ /^IIII\x04\0/',
  174. NotIFD => 1,
  175. SubDirectory => {
  176. TagTable => 'Image::ExifTool::HP::Type4',
  177. Start => '$valuePtr',
  178. ByteOrder => 'LittleEndian',
  179. },
  180. },
  181. {
  182. Name => 'MakerNoteHP6', # PhotoSmart M425, M525 and M527
  183. Condition => '$$valPt =~ /^IIII\x06\0/',
  184. NotIFD => 1,
  185. SubDirectory => {
  186. TagTable => 'Image::ExifTool::HP::Type6',
  187. Start => '$valuePtr',
  188. ByteOrder => 'LittleEndian',
  189. },
  190. },
  191. {
  192. Name => 'MakerNoteISL', # (used in Samsung GX20 samples)
  193. Condition => '$$valPt =~ /^ISLMAKERNOTE000\0/',
  194. # this maker notes starts with a TIFF-like header at offset 0x10
  195. SubDirectory => {
  196. TagTable => 'Image::ExifTool::Unknown::Main',
  197. Start => '$valuePtr + 24',
  198. Base => '$start - 8',
  199. ByteOrder => 'Unknown',
  200. },
  201. },
  202. {
  203. Name => 'MakerNoteJVC',
  204. Condition => '$$valPt=~/^JVC /',
  205. SubDirectory => {
  206. TagTable => 'Image::ExifTool::JVC::Main',
  207. Start => '$valuePtr + 4',
  208. ByteOrder => 'Unknown',
  209. },
  210. },
  211. {
  212. Name => 'MakerNoteJVCText',
  213. Condition => '$$self{Make}=~/^(JVC|Victor)/ and $$valPt=~/^VER:/',
  214. NotIFD => 1,
  215. SubDirectory => {
  216. TagTable => 'Image::ExifTool::JVC::Text',
  217. },
  218. },
  219. {
  220. Name => 'MakerNoteKodak1a',
  221. Condition => '$$self{Make}=~/^EASTMAN KODAK/ and $$valPt=~/^KDK INFO/',
  222. NotIFD => 1,
  223. SubDirectory => {
  224. TagTable => 'Image::ExifTool::Kodak::Main',
  225. Start => '$valuePtr + 8',
  226. ByteOrder => 'BigEndian',
  227. },
  228. },
  229. {
  230. Name => 'MakerNoteKodak1b',
  231. Condition => '$$self{Make}=~/^EASTMAN KODAK/ and $$valPt=~/^KDK/',
  232. NotIFD => 1,
  233. SubDirectory => {
  234. TagTable => 'Image::ExifTool::Kodak::Main',
  235. Start => '$valuePtr + 8',
  236. ByteOrder => 'LittleEndian',
  237. },
  238. },
  239. {
  240. # used by various Kodak, HP, Pentax and Minolta models
  241. Name => 'MakerNoteKodak2',
  242. Condition => q{
  243. $$valPt =~ /^.{8}Eastman Kodak/s or
  244. $$valPt =~ /^\x01\0[\0\x01]\0\0\0\x04\0[a-zA-Z]{4}/
  245. },
  246. NotIFD => 1,
  247. SubDirectory => {
  248. TagTable => 'Image::ExifTool::Kodak::Type2',
  249. ByteOrder => 'BigEndian',
  250. },
  251. },
  252. {
  253. # not much to key on here, but we know the
  254. # upper byte of the year should be 0x07:
  255. Name => 'MakerNoteKodak3',
  256. Condition => q{
  257. $$self{Make} =~ /^EASTMAN KODAK/ and
  258. $$valPt =~ /^(?!MM|II).{12}\x07/s and
  259. $$valPt !~ /^(MM|II|AOC)/
  260. },
  261. NotIFD => 1,
  262. SubDirectory => {
  263. TagTable => 'Image::ExifTool::Kodak::Type3',
  264. ByteOrder => 'BigEndian',
  265. },
  266. },
  267. {
  268. Name => 'MakerNoteKodak4',
  269. Condition => q{
  270. $$self{Make} =~ /^Eastman Kodak/ and
  271. $$valPt =~ /^.{41}JPG/s and
  272. $$valPt !~ /^(MM|II|AOC)/
  273. },
  274. NotIFD => 1,
  275. SubDirectory => {
  276. TagTable => 'Image::ExifTool::Kodak::Type4',
  277. ByteOrder => 'BigEndian',
  278. },
  279. },
  280. {
  281. Name => 'MakerNoteKodak5',
  282. Condition => q{
  283. $$self{Make}=~/^EASTMAN KODAK/ and
  284. ($$self{Model}=~/CX(4200|4230|4300|4310|6200|6230)/ or
  285. # try to pick up similar models we haven't tested yet
  286. $$valPt=~/^\0(\x1a\x18|\x3a\x08|\x59\xf8|\x14\x80)\0/)
  287. },
  288. NotIFD => 1,
  289. SubDirectory => {
  290. TagTable => 'Image::ExifTool::Kodak::Type5',
  291. ByteOrder => 'BigEndian',
  292. },
  293. },
  294. {
  295. Name => 'MakerNoteKodak6a',
  296. Condition => q{
  297. $$self{Make}=~/^EASTMAN KODAK/ and
  298. $$self{Model}=~/DX3215/
  299. },
  300. NotIFD => 1,
  301. SubDirectory => {
  302. TagTable => 'Image::ExifTool::Kodak::Type6',
  303. ByteOrder => 'BigEndian',
  304. },
  305. },
  306. {
  307. Name => 'MakerNoteKodak6b',
  308. Condition => q{
  309. $$self{Make}=~/^EASTMAN KODAK/ and
  310. $$self{Model}=~/DX3700/
  311. },
  312. NotIFD => 1,
  313. SubDirectory => {
  314. TagTable => 'Image::ExifTool::Kodak::Type6',
  315. ByteOrder => 'LittleEndian',
  316. },
  317. },
  318. {
  319. Name => 'MakerNoteKodak7',
  320. # look for something that looks like a serial number
  321. # (confirmed serial numbers have the format KXXXX########, but we also
  322. # accept other strings from sample images that may be serial numbers)
  323. Condition => q{
  324. $$self{Make}=~/Kodak/i and
  325. $$valPt =~ /^[CK][A-Z\d]{3} ?[A-Z\d]{1,2}\d{2}[A-Z\d]\d{4}[ \0]/
  326. },
  327. NotIFD => 1,
  328. SubDirectory => {
  329. TagTable => 'Image::ExifTool::Kodak::Type7',
  330. ByteOrder => 'LittleEndian',
  331. },
  332. },
  333. {
  334. Name => 'MakerNoteKodak8a',
  335. # IFD-format maker notes: look for reasonable number of
  336. # entries and check format and count of first IFD entry
  337. Condition => q{
  338. $$self{Make}=~/Kodak/i and
  339. ($$valPt =~ /^\0[\x02-\x7f]..\0[\x01-\x0c]\0\0/s or
  340. $$valPt =~ /^[\x02-\x7f]\0..[\x01-\x0c]\0..\0\0/s)
  341. },
  342. SubDirectory => {
  343. TagTable => 'Image::ExifTool::Kodak::Type8',
  344. ProcessProc => \&ProcessUnknown,
  345. ByteOrder => 'Unknown',
  346. },
  347. },
  348. {
  349. Name => 'MakerNoteKodak8b',
  350. # these maker notes have an extra 2 bytes after the entry count
  351. # (this is handled by the patch). Also, the IFD uses a Format 13,
  352. # which is some 2-byte format (not Float, as decoded by ExifTool)
  353. # - written by the PixPro AZ251, AZ361, AZ262, AZ521
  354. Condition => q{
  355. $$self{Make}=~/Kodak/i and
  356. $$valPt =~ /^MM\0\x2a\0\0\0\x08\0.\0\0/
  357. },
  358. SubDirectory => {
  359. TagTable => 'Image::ExifTool::Kodak::Type8',
  360. ProcessProc => \&ProcessKodakPatch,
  361. ByteOrder => 'BigEndian',
  362. Start => '$valuePtr + 8',
  363. Base => '$start - 8',
  364. },
  365. },
  366. {
  367. Name => 'MakerNoteKodak8c',
  368. # TIFF-format maker notes
  369. Condition => q{
  370. $$self{Make}=~/Kodak/i and
  371. $$valPt =~ /^(MM\0\x2a\0\0\0\x08|II\x2a\0\x08\0\0\0)/
  372. },
  373. SubDirectory => {
  374. TagTable => 'Image::ExifTool::Kodak::Type8',
  375. ProcessProc => \&ProcessUnknown,
  376. ByteOrder => 'Unknown',
  377. Start => '$valuePtr + 8',
  378. Base => '$start - 8',
  379. },
  380. },
  381. {
  382. Name => 'MakerNoteKodak9',
  383. # test header and Kodak:DateTimeOriginal
  384. Condition => '$$valPt =~ m{^IIII[\x02\x03]\0.{14}\d{4}/\d{2}/\d{2} }s',
  385. NotIFD => 1,
  386. SubDirectory => {
  387. TagTable => 'Image::ExifTool::Kodak::Type9',
  388. ByteOrder => 'LittleEndian',
  389. },
  390. },
  391. {
  392. Name => 'MakerNoteKodak10',
  393. # yet another type of Kodak IFD-format maker notes:
  394. # this type begins with a byte order indicator,
  395. # followed immediately by the IFD
  396. Condition => q{
  397. $$self{Make}=~/Kodak/i and
  398. $$valPt =~ /^(MM\0[\x02-\x7f]|II[\x02-\x7f]\0)/
  399. },
  400. SubDirectory => {
  401. TagTable => 'Image::ExifTool::Kodak::Type10',
  402. ProcessProc => \&ProcessUnknown,
  403. ByteOrder => 'Unknown',
  404. Start => '$valuePtr + 2',
  405. },
  406. },
  407. {
  408. Name => 'MakerNoteKodak11',
  409. # these maker notes have an extra 2 bytes after the entry count
  410. # - written by the PixPro S-1 (Note: Make is "JK Imaging, Ltd.", so check Model for "Kodak")
  411. Condition => q{
  412. $$self{Model}=~/Kodak/i and
  413. $$valPt =~ /^II\x2a\0\x08\0\0\0.\0\0\0/
  414. },
  415. SubDirectory => {
  416. TagTable => 'Image::ExifTool::Kodak::Type11',
  417. ProcessProc => \&ProcessKodakPatch,
  418. ByteOrder => 'LittleEndian',
  419. Start => '$valuePtr + 8',
  420. Base => '$start - 8',
  421. },
  422. },
  423. {
  424. Name => 'MakerNoteKodakUnknown',
  425. Condition => '$$self{Make}=~/Kodak/i and $$valPt!~/^AOC\0/',
  426. NotIFD => 1,
  427. SubDirectory => {
  428. TagTable => 'Image::ExifTool::Kodak::Unknown',
  429. ByteOrder => 'BigEndian',
  430. },
  431. },
  432. {
  433. Name => 'MakerNoteKyocera',
  434. # (starts with "KYOCERA")
  435. Condition => '$$valPt =~ /^KYOCERA/',
  436. SubDirectory => {
  437. TagTable => 'Image::ExifTool::Unknown::Main',
  438. Start => '$valuePtr + 22',
  439. Base => '$start + 2',
  440. EntryBased => 1,
  441. ByteOrder => 'Unknown',
  442. },
  443. },
  444. {
  445. Name => 'MakerNoteMinolta',
  446. Condition => q{
  447. $$self{Make}=~/^(Konica Minolta|Minolta)/i and
  448. $$valPt !~ /^(MINOL|CAMER|MLY0|KC|\+M\+M|\xd7)/
  449. },
  450. SubDirectory => {
  451. TagTable => 'Image::ExifTool::Minolta::Main',
  452. ByteOrder => 'Unknown',
  453. },
  454. },
  455. {
  456. # the DiMAGE E323 (MINOL) and E500 (CAMER), and some models
  457. # of Mustek, Pentax, Ricoh and Vivitar (CAMER).
  458. Name => 'MakerNoteMinolta2',
  459. Condition => '$$valPt =~ /^(MINOL|CAMER)\0/ and $$self{OlympusCAMER} = 1',
  460. SubDirectory => {
  461. # these models use Olympus tags in the range 0x200-0x221 plus 0xf00
  462. TagTable => 'Image::ExifTool::Olympus::Main',
  463. Start => '$valuePtr + 8',
  464. ByteOrder => 'Unknown',
  465. },
  466. },
  467. {
  468. # /^MLY0/ - DiMAGE G400, G500, G530, G600
  469. # /^KC/ - Revio KD-420Z, DiMAGE E203
  470. # /^+M+M/ - DiMAGE E201
  471. # /^\xd7/ - DiMAGE RD3000
  472. Name => 'MakerNoteMinolta3',
  473. Condition => '$$self{Make} =~ /^(Konica Minolta|Minolta)/i',
  474. Binary => 1,
  475. Notes => 'not EXIF-based',
  476. },
  477. {
  478. Name => 'MakerNoteMotorola',
  479. Condition => '$$valPt=~/^MOT\0/',
  480. SubDirectory => {
  481. TagTable => 'Image::ExifTool::Motorola::Main',
  482. Start => '$valuePtr + 8',
  483. Base => '$start - 8',
  484. ByteOrder => 'Unknown',
  485. },
  486. },
  487. {
  488. # older Nikon maker notes
  489. Name => 'MakerNoteNikon2',
  490. Condition => '$$valPt=~/^Nikon\x00\x01/',
  491. SubDirectory => {
  492. TagTable => 'Image::ExifTool::Nikon::Type2',
  493. Start => '$valuePtr + 8',
  494. ByteOrder => 'LittleEndian',
  495. },
  496. },
  497. {
  498. # headerless Nikon maker notes
  499. Name => 'MakerNoteNikon3',
  500. Condition => '$$self{Make}=~/^NIKON/i',
  501. SubDirectory => {
  502. TagTable => 'Image::ExifTool::Nikon::Main',
  503. ByteOrder => 'Unknown', # most are little-endian, but D1 is big
  504. },
  505. },
  506. {
  507. Name => 'MakerNoteNintendo',
  508. # (starts with an IFD)
  509. Condition => '$$self{Make} eq "Nintendo"',
  510. SubDirectory => {
  511. TagTable => 'Image::ExifTool::Nintendo::Main',
  512. ByteOrder => 'Unknown',
  513. },
  514. },
  515. {
  516. Name => 'MakerNoteOlympus',
  517. # (if Make is 'SEIKO EPSON CORP.', starts with "EPSON\0")
  518. # (if Make is 'OLYMPUS OPTICAL CO.,LTD' or 'OLYMPUS CORPORATION',
  519. # starts with "OLYMP\0")
  520. Condition => '$$valPt =~ /^(OLYMP|EPSON)\0/',
  521. SubDirectory => {
  522. TagTable => 'Image::ExifTool::Olympus::Main',
  523. Start => '$valuePtr + 8',
  524. ByteOrder => 'Unknown',
  525. },
  526. },
  527. {
  528. Name => 'MakerNoteOlympus2',
  529. # new Olympus maker notes start with "OLYMPUS\0"
  530. Condition => '$$valPt =~ /^OLYMPUS\0/',
  531. SubDirectory => {
  532. TagTable => 'Image::ExifTool::Olympus::Main',
  533. Start => '$valuePtr + 12',
  534. Base => '$start - 12',
  535. ByteOrder => 'Unknown',
  536. },
  537. },
  538. {
  539. Name => 'MakerNoteLeica',
  540. # (starts with "LEICA\0\0\0")
  541. Condition => '$$self{Make} eq "LEICA"',
  542. SubDirectory => {
  543. # many Leica models use the same format as Panasonic
  544. TagTable => 'Image::ExifTool::Panasonic::Main',
  545. Start => '$valuePtr + 8',
  546. ByteOrder => 'Unknown',
  547. },
  548. },
  549. {
  550. Name => 'MakerNoteLeica2', # used by the M8
  551. # (starts with "LEICA\0\0\0")
  552. Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA\0\0\0/',
  553. SubDirectory => {
  554. TagTable => 'Image::ExifTool::Panasonic::Leica2',
  555. # (the offset base is different in JPEG and DNG images, but we
  556. # can copy makernotes from one to the other, so we need special
  557. # logic to decide which base to apply)
  558. ProcessProc => \&FixLeicaBase,
  559. Start => '$valuePtr + 8',
  560. Base => '$start', # (- 8 for DNG images!)
  561. ByteOrder => 'Unknown',
  562. },
  563. },
  564. {
  565. Name => 'MakerNoteLeica3', # used by the R8 and R9
  566. # (starts with IFD)
  567. Condition => q{
  568. $$self{Make} =~ /^Leica Camera AG/ and $$valPt !~ /^LEICA/ and
  569. $$self{Model} ne "S2" and $$self{Model} ne "LEICA M (Typ 240)"
  570. },
  571. SubDirectory => {
  572. TagTable => 'Image::ExifTool::Panasonic::Leica3',
  573. Start => '$valuePtr',
  574. ByteOrder => 'Unknown',
  575. },
  576. },
  577. {
  578. Name => 'MakerNoteLeica4', # used by the M9/M-Monochrom
  579. # (M9 and M Monochrom start with "LEICA0\x03\0")
  580. Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA0/',
  581. SubDirectory => {
  582. TagTable => 'Image::ExifTool::Panasonic::Leica4',
  583. Start => '$valuePtr + 8',
  584. Base => '$start - 8', # (yay! Leica fixed the M8 problem)
  585. ByteOrder => 'Unknown',
  586. },
  587. },
  588. {
  589. Name => 'MakerNoteLeica5', # used by the X1/X2/X VARIO/T
  590. # (X1 starts with "LEICA\0\x01\0", Make is "LEICA CAMERA AG")
  591. # (X2 starts with "LEICA\0\x05\0", Make is "LEICA CAMERA AG")
  592. # (X VARIO starts with "LEICA\0\x04\0", Make is "LEICA CAMERA AG")
  593. # (T (Typ 701) starts with "LEICA\0\0x6", Make is "LEICA CAMERA AG")
  594. # (X (Typ 113) starts with "LEICA\0\0x7", Make is "LEICA CAMERA AG")
  595. Condition => '$$valPt =~ /^LEICA\0[\x01\x04\x05\x06\x07]\0/',
  596. SubDirectory => {
  597. TagTable => 'Image::ExifTool::Panasonic::Leica5',
  598. Start => '$valuePtr + 8',
  599. Base => '$start - 8',
  600. ByteOrder => 'Unknown',
  601. },
  602. },
  603. {
  604. Name => 'MakerNoteLeica6', # used by the S2, M (Typ 240) and S (Typ 006)
  605. # (starts with "LEICA\0\x02\xff", Make is "Leica Camera AG", but test the
  606. # model names separately because the maker notes data may not be loaded
  607. # at the time this is tested if they are in a JPEG trailer. Also, this
  608. # header is used by the M Monochrom (Type 246), with different offsets.)
  609. Condition => q{
  610. ($$self{Make} eq 'Leica Camera AG' and ($$self{Model} eq 'S2' or
  611. $$self{Model} eq 'LEICA M (Typ 240)' or $$self{Model} eq 'LEICA S (Typ 006)'))
  612. },
  613. DataTag => 'LeicaTrailer', # (generates fixup name for this tag)
  614. LeicaTrailer => 1, # flag to special-case this tag in the Exif code
  615. SubDirectory => {
  616. TagTable => 'Image::ExifTool::Panasonic::Leica6',
  617. Start => '$valuePtr + 8',
  618. ByteOrder => 'Unknown',
  619. # NOTE: Leica uses absolute file offsets when this maker note is stored
  620. # as a JPEG trailer -- this case is handled by ProcessLeicaTrailer in
  621. # Panasonic.pm, and any "Base" defined here is ignored for this case.
  622. # ExifTool may also create S2/M maker notes inside the APP1 segment when
  623. # copying from other files, and for this the normal EXIF offsets are used,
  624. # Base should not be defined!
  625. },
  626. },
  627. {
  628. Name => 'MakerNoteLeica7', # used by the M Monochrom (Typ 246)
  629. # (starts with "LEICA\0\x02\xff", Make is "Leica Camera AG")
  630. Condition => '$$valPt =~ /^LEICA\0\x02\xff/',
  631. DataTag => 'LeicaTrailer', # (generates fixup name for this tag)
  632. LeicaTrailer => 1, # flag to special-case this tag in the Exif code
  633. SubDirectory => {
  634. TagTable => 'Image::ExifTool::Panasonic::Leica6',
  635. Start => '$valuePtr + 8',
  636. ByteOrder => 'Unknown',
  637. Base => '-$base', # uses absolute file offsets
  638. },
  639. },
  640. {
  641. Name => 'MakerNoteLeica8', # used by the Q (Type 116)
  642. # (Q (Typ 116) starts with "LEICA\0\x08\0", Make is "LEICA CAMERA AG")
  643. # (SL (Typ 601) starts with "LEICA\0\x09\0", Make is "LEICA CAMERA AG")
  644. Condition => '$$valPt =~ /^LEICA\0[\x08\x09]\0/',
  645. SubDirectory => {
  646. TagTable => 'Image::ExifTool::Panasonic::Leica5',
  647. Start => '$valuePtr + 8',
  648. ByteOrder => 'Unknown',
  649. },
  650. },
  651. {
  652. Name => 'MakerNoteLeica9', # used by the M9/M-Monochrom
  653. # (M9 and M Monochrom start with "LEICA0\x03\0")
  654. Condition => '$$self{Make} =~ /^Leica Camera AG/ and $$valPt =~ /^LEICA\0\x02\0/',
  655. SubDirectory => {
  656. TagTable => 'Image::ExifTool::Panasonic::Leica9',
  657. Start => '$valuePtr + 8',
  658. Base => '$start - 8',
  659. ByteOrder => 'Unknown',
  660. },
  661. },
  662. {
  663. Name => 'MakerNotePanasonic',
  664. # (starts with "Panasonic\0")
  665. Condition => '$$valPt=~/^Panasonic/',
  666. SubDirectory => {
  667. TagTable => 'Image::ExifTool::Panasonic::Main',
  668. Start => '$valuePtr + 12',
  669. ByteOrder => 'Unknown',
  670. },
  671. },
  672. {
  673. Name => 'MakerNotePanasonic2',
  674. # (starts with "Panasonic\0")
  675. Condition => '$$self{Make}=~/^Panasonic/ and $$valPt=~/^MKE/',
  676. SubDirectory => {
  677. TagTable => 'Image::ExifTool::Panasonic::Type2',
  678. ByteOrder => 'LittleEndian',
  679. },
  680. },
  681. {
  682. Name => 'MakerNotePentax',
  683. # (starts with "AOC\0", but so does MakerNotePentax3)
  684. # (also used by some Samsung models)
  685. Condition => q{
  686. $$valPt=~/^AOC\0/ and
  687. $$self{Model} !~ /^PENTAX Optio ?[34]30RS\s*$/
  688. },
  689. SubDirectory => {
  690. TagTable => 'Image::ExifTool::Pentax::Main',
  691. # process as Unknown maker notes because the start offset and
  692. # byte ordering are so variable
  693. ProcessProc => \&ProcessUnknown,
  694. # offsets can be totally whacky for Pentax maker notes,
  695. # so attempt to fix the offset base if possible
  696. FixBase => 1,
  697. ByteOrder => 'Unknown',
  698. },
  699. },
  700. {
  701. Name => 'MakerNotePentax2',
  702. # (starts with an IFD)
  703. # Casio-like maker notes used only by the Optio 330 and 430
  704. Condition => '$$self{Make}=~/^Asahi/ and $$valPt!~/^AOC\0/',
  705. SubDirectory => {
  706. TagTable => 'Image::ExifTool::Pentax::Type2',
  707. ProcessProc => \&ProcessUnknown,
  708. FixBase => 1,
  709. ByteOrder => 'Unknown',
  710. },
  711. },
  712. {
  713. Name => 'MakerNotePentax3',
  714. # (starts with "AOC\0", like the more common Pentax maker notes)
  715. # Casio maker notes used only by the Optio 330RS and 430RS
  716. Condition => '$$self{Make}=~/^Asahi/',
  717. SubDirectory => {
  718. TagTable => 'Image::ExifTool::Casio::Type2',
  719. ProcessProc => \&ProcessUnknown,
  720. FixBase => 1,
  721. ByteOrder => 'Unknown',
  722. },
  723. },
  724. {
  725. Name => 'MakerNotePentax4',
  726. # (starts with 3 or 4 digits)
  727. # HP2-like text-based maker notes used by Optio E20
  728. Condition => '$$self{Make}=~/^PENTAX/ and $$valPt=~/^\d{3}/',
  729. NotIFD => 1,
  730. SubDirectory => {
  731. TagTable => 'Image::ExifTool::Pentax::Type4',
  732. Start => '$valuePtr',
  733. ByteOrder => 'LittleEndian',
  734. },
  735. },
  736. {
  737. Name => 'MakerNotePentax5',
  738. # (starts with "PENTAX \0")
  739. # used by cameras such as the Q, Optio S1, RS1500 and WG-1
  740. Condition => '$$valPt=~/^PENTAX \0/',
  741. SubDirectory => {
  742. TagTable => 'Image::ExifTool::Pentax::Main',
  743. Start => '$valuePtr + 10',
  744. Base => '$start - 10',
  745. ByteOrder => 'Unknown',
  746. },
  747. },
  748. {
  749. Name => 'MakerNotePentax6',
  750. # (starts with "S1\0\0\0\0\0\0\x0c\0\0\0")
  751. Condition => '$$valPt=~/^S1\0{6}\x0c\0{3}/',
  752. SubDirectory => {
  753. TagTable => 'Image::ExifTool::Pentax::S1',
  754. Start => '$valuePtr + 12',
  755. Base => '$start - 12',
  756. ByteOrder => 'Unknown',
  757. },
  758. },
  759. {
  760. Name => 'MakerNotePhaseOne',
  761. # Starts with: 'IIIITwaR' or 'IIIICwaR' (have seen both written by P25)
  762. # (have also seen code which expects 'MMMMRawT')
  763. Condition => q{
  764. return undef unless $$valPt =~ /^(IIII.waR|MMMMRaw.)/s;
  765. $self->OverrideFileType($$self{TIFF_TYPE} = 'IIQ') if $count > 1000000;
  766. return 1;
  767. },
  768. NotIFD => 1,
  769. SubDirectory => { TagTable => 'Image::ExifTool::PhaseOne::Main' },
  770. PutFirst => 1, # place immediately after TIFF header
  771. },
  772. {
  773. Name => 'MakerNoteReconyx',
  774. Condition => q{
  775. $$valPt =~ /^\x01\xf1([\x02\x03]\x00)?/ and
  776. ($1 or $$self{Make} eq "RECONYX")
  777. },
  778. SubDirectory => {
  779. TagTable => 'Image::ExifTool::Reconyx::Main',
  780. ByteOrder => 'Little-endian',
  781. },
  782. },
  783. {
  784. Name => 'MakerNoteRicoh',
  785. # (my test R50 image starts with " \x02\x01" - PH)
  786. Condition => q{
  787. $$self{Make} =~ /^(PENTAX )?RICOH/ and
  788. $$valPt =~ /^(Ricoh| |MM\0\x2a|II\x2a\0)/i and
  789. $$valPt !~ /^(MM\0\x2a\0\0\0\x08\0.\0\0|II\x2a\0\x08\0\0\0.\0\0\0)/s and
  790. $$self{Model} ne 'RICOH WG-M1'
  791. },
  792. SubDirectory => {
  793. TagTable => 'Image::ExifTool::Ricoh::Main',
  794. Start => '$valuePtr + 8',
  795. ByteOrder => 'Unknown',
  796. },
  797. },
  798. {
  799. Name => 'MakerNoteRicoh2',
  800. # (the Ricoh HZ15 starts with "MM\0\x2a" and the Pentax XG-1 starts with "II\x2a\0",
  801. # but an extra 2 bytes of padding after the IFD entry count prevents these from
  802. # being processed as a standard IFD. Note that the offsets for the HZ15 are all
  803. # zeros, but they seem to be mostly OK for the XG-1)
  804. Condition => q{
  805. $$self{Make} =~ /^(PENTAX )?RICOH/ and ($$self{Model} eq 'RICOH WG-M1' or
  806. $$valPt =~ /^(MM\0\x2a\0\0\0\x08\0.\0\0|II\x2a\0\x08\0\0\0.\0\0\0)/s)
  807. },
  808. SubDirectory => {
  809. TagTable => 'Image::ExifTool::Ricoh::Type2',
  810. Start => '$valuePtr + 8',
  811. Base => '$start - 8',
  812. ByteOrder => 'Unknown',
  813. ProcessProc => \&ProcessKodakPatch,
  814. },
  815. },
  816. {
  817. Name => 'MakerNoteRicohText',
  818. Condition => '$$self{Make}=~/^RICOH/',
  819. NotIFD => 1,
  820. SubDirectory => {
  821. TagTable => 'Image::ExifTool::Ricoh::Text',
  822. ByteOrder => 'Unknown',
  823. },
  824. },
  825. {
  826. Name => 'MakerNoteSamsung1a',
  827. # Samsung STMN maker notes WITHOUT PreviewImage
  828. Condition => '$$valPt =~ /^STMN\d{3}.\0{4}/s',
  829. Binary => 1,
  830. Notes => 'Samsung "STMN" maker notes without PreviewImage',
  831. },
  832. {
  833. Name => 'MakerNoteSamsung1b',
  834. # Samsung STMN maker notes WITH PreviewImage
  835. Condition => '$$valPt =~ /^STMN\d{3}/',
  836. SubDirectory => {
  837. TagTable => 'Image::ExifTool::Samsung::Main',
  838. },
  839. },
  840. {
  841. Name => 'MakerNoteSamsung2',
  842. # Samsung EXIF-format maker notes
  843. Condition => q{
  844. $$self{Make} eq 'SAMSUNG' and ($$self{TIFF_TYPE} eq 'SRW' or
  845. $$valPt=~/^(\0.\0\x01\0\x07\0{3}\x04|.\0\x01\0\x07\0\x04\0{3})0100/s)
  846. },
  847. SubDirectory => {
  848. TagTable => 'Image::ExifTool::Samsung::Type2',
  849. # Samsung is very inconsistent here, and uses absolute offsets for some
  850. # models and relative offsets for others, so process as Unknown
  851. ProcessProc => \&ProcessUnknown,
  852. FixBase => 1,
  853. ByteOrder => 'Unknown',
  854. },
  855. },
  856. {
  857. Name => 'MakerNoteSanyo',
  858. # (starts with "SANYO\0")
  859. Condition => '$$self{Make}=~/^SANYO/ and $$self{Model}!~/^(C4|J\d|S\d)\b/',
  860. SubDirectory => {
  861. TagTable => 'Image::ExifTool::Sanyo::Main',
  862. Validate => '$val =~ /^SANYO/',
  863. Start => '$valuePtr + 8',
  864. ByteOrder => 'Unknown',
  865. },
  866. },
  867. {
  868. Name => 'MakerNoteSanyoC4',
  869. # The C4 offsets are wrong by 12, so they must be fixed
  870. Condition => '$$self{Make}=~/^SANYO/ and $$self{Model}=~/^C4\b/',
  871. SubDirectory => {
  872. TagTable => 'Image::ExifTool::Sanyo::Main',
  873. Validate => '$val =~ /^SANYO/',
  874. Start => '$valuePtr + 8',
  875. FixBase => 1,
  876. ByteOrder => 'Unknown',
  877. },
  878. },
  879. {
  880. Name => 'MakerNoteSanyoPatch',
  881. # The J1, J2, J4, S1, S3 and S4 offsets are completely screwy
  882. Condition => '$$self{Make}=~/^SANYO/',
  883. SubDirectory => {
  884. TagTable => 'Image::ExifTool::Sanyo::Main',
  885. Validate => '$val =~ /^SANYO/',
  886. Start => '$valuePtr + 8',
  887. ByteOrder => 'Unknown',
  888. FixOffsets => 'Image::ExifTool::Sanyo::FixOffsets($valuePtr, $valEnd, $size, $tagID, $wFlag)',
  889. },
  890. },
  891. {
  892. Name => 'MakerNoteSigma',
  893. # (starts with "SIGMA\0")
  894. Condition => '$$self{Make}=~/^(SIGMA|FOVEON)/',
  895. SubDirectory => {
  896. TagTable => 'Image::ExifTool::Sigma::Main',
  897. Validate => '$val =~ /^(SIGMA|FOVEON)/',
  898. Start => '$valuePtr + 10',
  899. ByteOrder => 'Unknown',
  900. },
  901. },
  902. {
  903. Name => 'MakerNoteSony',
  904. # (starts with "SONY DSC \0" or "SONY CAM \0")
  905. # (TF1 starts with "\0\0SONY PIC\0")
  906. # (Hasselblad models start with "VHAB \0")
  907. Condition => '$$valPt=~/^(SONY (DSC|CAM|MOBILE)|\0\0SONY PIC\0|VHAB \0)/',
  908. SubDirectory => {
  909. TagTable => 'Image::ExifTool::Sony::Main',
  910. Start => '$valuePtr + 12',
  911. ByteOrder => 'Unknown',
  912. },
  913. },
  914. {
  915. Name => 'MakerNoteSony2',
  916. # (starts with "SONY PI\0" -- DSC-S650/S700/S750)
  917. Condition => '$$valPt=~/^SONY PI\0/ and $$self{OlympusCAMER}=1',
  918. SubDirectory => {
  919. TagTable => 'Image::ExifTool::Olympus::Main',
  920. Start => '$valuePtr + 12',
  921. ByteOrder => 'Unknown',
  922. },
  923. },
  924. {
  925. Name => 'MakerNoteSony3',
  926. # (starts with "PREMI\0" -- DSC-S45/S500)
  927. Condition => '$$valPt=~/^(PREMI)\0/ and $$self{OlympusCAMER}=1',
  928. SubDirectory => {
  929. TagTable => 'Image::ExifTool::Olympus::Main',
  930. Start => '$valuePtr + 8',
  931. ByteOrder => 'Unknown',
  932. },
  933. },
  934. {
  935. Name => 'MakerNoteSony4',
  936. # (starts with "SONY PIC\0" -- DSC-H200/J20/W370/W510, MHS-TS20)
  937. Condition => '$$valPt=~/^SONY PIC\0/',
  938. SubDirectory => { TagTable => 'Image::ExifTool::Sony::PIC' },
  939. },
  940. {
  941. Name => 'MakerNoteSony5', # used in SR2 and ARW images
  942. Condition => '$$self{Make}=~/^SONY/ and $$valPt!~/^\x01\x00/',
  943. SubDirectory => {
  944. TagTable => 'Image::ExifTool::Sony::Main',
  945. Start => '$valuePtr',
  946. ByteOrder => 'Unknown',
  947. },
  948. },
  949. {
  950. Name => 'MakerNoteSonyEricsson',
  951. Condition => '$$valPt =~ /^SEMC MS\0/',
  952. SubDirectory => {
  953. TagTable => 'Image::ExifTool::Sony::Ericsson',
  954. Start => '$valuePtr + 20',
  955. Base => '$start - 8',
  956. ByteOrder => 'Unknown',
  957. },
  958. },
  959. {
  960. Name => 'MakerNoteSonySRF',
  961. Condition => '$$self{Make}=~/^SONY/',
  962. SubDirectory => {
  963. TagTable => 'Image::ExifTool::Sony::SRF',
  964. Start => '$valuePtr',
  965. ByteOrder => 'Unknown',
  966. },
  967. },
  968. {
  969. Name => 'MakerNoteUnknownText',
  970. Condition => '$$valPt =~ /^[\x09\x0d\x0a\x20-\x7e]+\0*$/',
  971. Notes => 'unknown text-based maker notes',
  972. # show as binary if it is too long
  973. ValueConv => 'length($val) > 64 ? \$val : $val',
  974. ValueConvInv => '$val',
  975. },
  976. {
  977. Name => 'MakerNoteUnknownBinary',
  978. # "LSI1\0" - SilverFast
  979. Condition => '$$valPt =~ /^LSI1\0/',
  980. Notes => 'unknown binary maker notes',
  981. Binary => 1,
  982. },
  983. {
  984. Name => 'MakerNoteUnknown',
  985. PossiblePreview => 1,
  986. SubDirectory => {
  987. TagTable => 'Image::ExifTool::Unknown::Main',
  988. ProcessProc => \&ProcessUnknownOrPreview,
  989. WriteProc => \&WriteUnknownOrPreview,
  990. ByteOrder => 'Unknown',
  991. FixBase => 2,
  992. },
  993. },
  994. );
  995. # insert writable properties so we can write our maker notes
  996. my $tagInfo;
  997. foreach $tagInfo (@Image::ExifTool::MakerNotes::Main) {
  998. $$tagInfo{Writable} = 'undef';
  999. $$tagInfo{Format} = 'undef', # (make sure we don't convert this when reading)
  1000. $$tagInfo{WriteGroup} = 'ExifIFD';
  1001. $$tagInfo{Groups} = { 1 => 'MakerNotes' };
  1002. next unless $$tagInfo{SubDirectory};
  1003. # make all SubDirectory tags block-writable
  1004. $$tagInfo{Binary} = 1,
  1005. $$tagInfo{MakerNotes} = 1;
  1006. }
  1007. #------------------------------------------------------------------------------
  1008. # Get normal offset of value data from end of maker note IFD
  1009. # Inputs: 0) ExifTool object reference
  1010. # Returns: Array: 0) relative flag (undef for no change)
  1011. # 1) normal offset from end of IFD to first value (empty if unknown)
  1012. # 2-N) other possible offsets used by some models
  1013. # Notes: Directory size should be validated before calling this routine
  1014. sub GetMakerNoteOffset($)
  1015. {
  1016. my $et = shift;
  1017. # figure out where we expect the value data based on camera type
  1018. my $make = $$et{Make};
  1019. my $model = $$et{Model};
  1020. my ($relative, @offsets);
  1021. # normally value data starts 4 bytes after end of directory, so this is the default.
  1022. # offsets of 0 and 4 are always allowed even if not specified,
  1023. # but the first offset specified is the one used when writing
  1024. if ($make =~ /^Canon/) {
  1025. push @offsets, ($model =~ /\b(20D|350D|REBEL XT|Kiss Digital N)\b/) ? 6 : 4;
  1026. # some Canon models (FV-M30, Optura50, Optura60) leave 24 unused bytes
  1027. # at the end of the IFD (2 spare IFD entries?)
  1028. push @offsets, 28 if $model =~ /\b(FV\b|OPTURA)/;
  1029. # some Canon PowerShot models leave 12 unused bytes
  1030. push @offsets, 16 if $model =~ /(PowerShot|IXUS|IXY)/;
  1031. } elsif ($make =~ /^CASIO/) {
  1032. # Casio AVI and MOV images use no padding, and their JPEG's use 4,
  1033. # except some models like the EX-S770,Z65,Z70,Z75 and Z700 which use 16,
  1034. # and the EX-Z35 which uses 2 (grrrr...)
  1035. push @offsets, $$et{FILE_TYPE} =~ /^(RIFF|MOV)$/ ? 0 : (4, 16, 2);
  1036. } elsif ($make =~ /^(General Imaging Co.|GEDSC IMAGING CORP.)/i) {
  1037. push @offsets, 0;
  1038. } elsif ($make =~ /^KYOCERA/) {
  1039. push @offsets, 12;
  1040. } elsif ($make =~ /^Leica Camera AG/) {
  1041. if ($model eq 'S2') {
  1042. # lots of empty space before first value in S2 images
  1043. push @offsets, 4, ($$et{FILE_TYPE} eq 'JPEG' ? 286 : 274);
  1044. } elsif ($model eq 'LEICA M MONOCHROM (Typ 246)') {
  1045. push @offsets, 4, 130;
  1046. } elsif ($model eq 'LEICA M (Typ 240)') {
  1047. push @offsets, 4, 118;
  1048. } elsif ($model =~ /^(R8|R9|M8)\b/) {
  1049. push @offsets, 6;
  1050. } else {
  1051. push @offsets, 4;
  1052. }
  1053. } elsif ($make =~ /^OLYMPUS/ and $model =~ /^E-(1|300|330)\b/) {
  1054. push @offsets, 16;
  1055. } elsif ($make =~ /^OLYMPUS/ and
  1056. # these Olympus models are just weird
  1057. $model =~ /^(C2500L|C-1Z?|C-5000Z|X-2|C720UZ|C725UZ|C150|C2Z|E-10|E-20|FerrariMODEL2003|u20D|u10D)\b/)
  1058. {
  1059. # no expected offset --> determine offset empirically via FixBase()
  1060. } elsif ($make =~ /^(Panasonic|JVC)\b/) {
  1061. push @offsets, 0;
  1062. } elsif ($make =~ /^SONY/) {
  1063. # earlier DSLR and "PREMI" models use an offset of 4
  1064. if ($model =~ /^(DSLR-.*|SLT-A(33|35|55V)|NEX-(3|5|C3|VG10E))$/ or
  1065. $$et{OlympusCAMER})
  1066. {
  1067. push @offsets, 4;
  1068. } else {
  1069. push @offsets, 0;
  1070. }
  1071. } elsif ($make eq 'FUJIFILM') {
  1072. # some models have offset of 6, so allow that too (A345,A350,A360,A370)
  1073. push @offsets, 4, 6;
  1074. } elsif ($make =~ /^TOSHIBA/) {
  1075. # similar to Canon, can also have 24 bytes of padding
  1076. push @offsets, 0, 24;
  1077. } elsif ($make =~ /^PENTAX/) {
  1078. push @offsets, 4;
  1079. # the Pentax addressing mode is determined automatically, but
  1080. # sometimes the algorithm gets it wrong, but Pentax always uses
  1081. # absolute addressing, so force it to be absolute
  1082. $relative = 0;
  1083. } elsif ($make =~ /^Konica Minolta/i) {
  1084. # patch for DiMAGE X50, Xg, Z2 and Z10
  1085. push @offsets, 4, -16;
  1086. } elsif ($make =~ /^Minolta/) {
  1087. # patch for DiMAGE 7, X20 and Z1
  1088. push @offsets, 4, -8, -12;
  1089. } else {
  1090. push @offsets, 4; # the normal offset
  1091. }
  1092. return ($relative, @offsets);
  1093. }
  1094. #------------------------------------------------------------------------------
  1095. # Get hash of value offsets / block sizes
  1096. # Inputs: 0) Data pointer, 1) offset to start of directory,
  1097. # 2) hash ref to return value pointers based on tag ID
  1098. # Returns: 0) hash reference: keys are offsets, values are block sizes
  1099. # 1) same thing, but with keys adjusted for value-based offsets
  1100. # Notes: Directory size should be validated before calling this routine
  1101. # - calculates MIN and MAX offsets in entry-based hash
  1102. sub GetValueBlocks($$;$)
  1103. {
  1104. my ($dataPt, $dirStart, $tagPtr) = @_;
  1105. my $numEntries = Get16u($dataPt, $dirStart);
  1106. my ($index, $valPtr, %valBlock, %valBlkAdj, $end);
  1107. for ($index=0; $index<$numEntries; ++$index) {
  1108. my $entry = $dirStart + 2 + 12 * $index;
  1109. my $format = Get16u($dataPt, $entry+2);
  1110. last if $format < 1 or $format > 13;
  1111. my $count = Get32u($dataPt, $entry+4);
  1112. my $size = $count * $Image::ExifTool::Exif::formatSize[$format];
  1113. next if $size <= 4;
  1114. $valPtr = Get32u($dataPt, $entry+8);
  1115. $tagPtr and $$tagPtr{Get16u($dataPt, $entry)} = $valPtr;
  1116. # save location and size of longest block at this offset
  1117. unless (defined $valBlock{$valPtr} and $valBlock{$valPtr} > $size) {
  1118. $valBlock{$valPtr} = $size;
  1119. }
  1120. # adjust for case of value-based offsets
  1121. $valPtr += 12 * $index;
  1122. unless (defined $valBlkAdj{$valPtr} and $valBlkAdj{$valPtr} > $size) {
  1123. $valBlkAdj{$valPtr} = $size;
  1124. my $end = $valPtr + $size;
  1125. if (defined $valBlkAdj{MIN}) {
  1126. # save minimum only if it has a value of 12 or greater
  1127. $valBlkAdj{MIN} = $valPtr if $valBlkAdj{MIN} < 12 or $valBlkAdj{MIN} > $valPtr;
  1128. $valBlkAdj{MAX} = $end if $valBlkAdj{MAX} > $end;
  1129. } else {
  1130. $valBlkAdj{MIN} = $valPtr;
  1131. $valBlkAdj{MAX} = $end;
  1132. }
  1133. }
  1134. }
  1135. return(\%valBlock, \%valBlkAdj);
  1136. }
  1137. #------------------------------------------------------------------------------
  1138. # Fix base for value offsets in maker notes IFD (if necessary)
  1139. # Inputs: 0) ExifTool object ref, 1) DirInfo hash ref
  1140. # Return: amount of base shift (and $dirInfo Base and DataPos are updated,
  1141. # FixedBy is set if offsets fixed, and Relative or EntryBased may be set)
  1142. sub FixBase($$)
  1143. {
  1144. local $_;
  1145. my ($et, $dirInfo) = @_;
  1146. # don't fix base if fixing offsets individually or if we don't want to fix them
  1147. return 0 if $$dirInfo{FixOffsets} or $$dirInfo{NoFixBase};
  1148. my $dataPt = $$dirInfo{DataPt};
  1149. my $dataPos = $$dirInfo{DataPos};
  1150. my $dirStart = $$dirInfo{DirStart} || 0;
  1151. my $entryBased = $$dirInfo{EntryBased};
  1152. my $dirName = $$dirInfo{DirName};
  1153. my $fixBase = $et->Options('FixBase');
  1154. my $setBase = (defined $fixBase and $fixBase ne '') ? 1 : 0;
  1155. my ($fix, $fixedBy, %tagPtr);
  1156. # get hash of value block positions
  1157. my ($valBlock, $valBlkAdj) = GetValueBlocks($dataPt, $dirStart, \%tagPtr);
  1158. return 0 unless %$valBlock;
  1159. # get sorted list of value offsets
  1160. my @valPtrs = sort { $a <=> $b } keys %$valBlock;
  1161. #
  1162. # handle special case of Canon maker notes with TIFF footer containing original offset
  1163. #
  1164. if ($$et{Make} =~ /^Canon/ and $$dirInfo{DirLen} > 8) {
  1165. my $footerPos = $dirStart + $$dirInfo{DirLen} - 8;
  1166. my $footer = substr($$dataPt, $footerPos, 8);
  1167. if ($footer =~ /^(II\x2a\0|MM\0\x2a)/ and # check for TIFF footer
  1168. substr($footer,0,2) eq GetByteOrder()) # validate byte ordering
  1169. {
  1170. my $oldOffset = Get32u(\$footer, 4);
  1171. my $newOffset = $dirStart + $dataPos;
  1172. if ($setBase) {
  1173. $fix = $fixBase;
  1174. } else {
  1175. $fix = $newOffset - $oldOffset;
  1176. return 0 unless $fix;
  1177. # Picasa and ACDSee have a bug where they update other offsets without
  1178. # updating the TIFF footer (PH - 2009/02/25), so test for this case:
  1179. # validate Canon maker note footer fix by checking offset of last value
  1180. my $maxPt = $valPtrs[-1] + $$valBlock{$valPtrs[-1]};
  1181. # compare to end of maker notes, taking 8-byte footer into account
  1182. my $endDiff = $dirStart + $$dirInfo{DirLen} - ($maxPt - $dataPos) - 8;
  1183. # ignore footer offset only if end difference is exactly correct
  1184. # (allow for possible padding byte, although I have never seen this)
  1185. if (not $endDiff or $endDiff == 1) {
  1186. $et->Warn('Canon maker note footer may be invalid (ignored)',1);
  1187. return 0;
  1188. }
  1189. }
  1190. $et->Warn("Adjusted $dirName base by $fix",1);
  1191. $$dirInfo{FixedBy} = $fix;
  1192. $$dirInfo{Base} += $fix;
  1193. $$dirInfo{DataPos} -= $fix;
  1194. return $fix;
  1195. }
  1196. }
  1197. #
  1198. # analyze value offsets to see if they need fixing. The first task is to determine
  1199. # the minimum valid offset used (this is tricky, because we have to weed out bad
  1200. # offsets written by some cameras)
  1201. #
  1202. my $minPt = $$dirInfo{MinOffset} = $valPtrs[0]; # if life were simple, this would be it
  1203. my $ifdLen = 2 + 12 * Get16u($$dirInfo{DataPt}, $dirStart);
  1204. my $ifdEnd = $dirStart + $ifdLen;
  1205. my ($relative, @offsets) = GetMakerNoteOffset($et);
  1206. my $makeDiff = $offsets[0];
  1207. my $verbose = $et->Options('Verbose');
  1208. my ($diff, $shift);
  1209. # calculate expected minimum value offset
  1210. my $expected = $dataPos + $ifdEnd + (defined $makeDiff ? $makeDiff : 4);
  1211. $debug and print "$expected expected\n";
  1212. # zero our counters
  1213. my ($countNeg12, $countZero, $countOverlap) = (0, 0, 0);
  1214. my ($valPtr, $last);
  1215. foreach $valPtr (@valPtrs) {
  1216. printf("%d - %d (%d)\n", $valPtr, $valPtr + $$valBlock{$valPtr},
  1217. $valPtr - ($last || 0)) if $debug;
  1218. if (defined $last) {
  1219. my $gap = $valPtr - $last;
  1220. if ($gap == 0 or $gap == 1) {
  1221. ++$countZero;
  1222. } elsif ($gap == -12 and not $entryBased) {
  1223. # you get this when value offsets are relative to the IFD entry
  1224. ++$countNeg12;
  1225. } elsif ($gap < 0) {
  1226. # any other negative difference indicates overlapping values
  1227. ++$countOverlap if $valPtr; # (but ignore zero value pointers)
  1228. } elsif ($gap >= $ifdLen) {
  1229. # ignore previous minimum if we took a jump to near the expected value
  1230. # (some values can be stored before the IFD)
  1231. $minPt = $valPtr if abs($valPtr - $expected) <= 4;
  1232. }
  1233. # an offset less than 12 is surely garbage, so ignore it
  1234. $minPt = $valPtr if $minPt < 12;
  1235. }
  1236. $last = $valPtr + $$valBlock{$valPtr};
  1237. }
  1238. # could this IFD be using entry-based offsets?
  1239. if ((($countNeg12 > $countZero and $$valBlkAdj{MIN} >= $ifdLen - 2) or
  1240. ($$valBlkAdj{MIN} == $ifdLen - 2 or $$valBlkAdj{MIN} == $ifdLen + 2)
  1241. ) and $$valBlkAdj{MAX} <= $$dirInfo{DirLen}-2)
  1242. {
  1243. # looks like these offsets are entry-based, so use the offsets
  1244. # which have been correcting for individual entry position
  1245. $entryBased = 1;
  1246. $verbose and $et->Warn("$dirName offsets are entry-based",1);
  1247. } else {
  1248. # calculate offset difference from end of IFD to first value
  1249. $diff = ($minPt - $dataPos) - $ifdEnd;
  1250. $shift = 0;
  1251. $countOverlap and $et->Warn("Overlapping $dirName values",1);
  1252. if ($entryBased) {
  1253. $et->Warn("$dirName offsets do NOT look entry-based",1);
  1254. undef $entryBased;
  1255. undef $relative;
  1256. }
  1257. # use PrintIM tag to do special check for correct absolute offsets
  1258. if ($tagPtr{0xe00}) {
  1259. my $ptr = $tagPtr{0xe00} - $dataPos;
  1260. return 0 if $ptr > 0 and $ptr <= length($$dataPt) - 8 and
  1261. substr($$dataPt, $ptr, 8) eq "PrintIM\0";
  1262. }
  1263. # allow a range of reasonable differences for Unknown maker notes
  1264. if ($$dirInfo{FixBase} and $$dirInfo{FixBase} == 2) {
  1265. return 0 if $diff >=0 and $diff <= 24;
  1266. }
  1267. # ******** (used for testing to extract differences) ********
  1268. # $et->FoundTag('Diff', $diff);
  1269. # $et->FoundTag('MakeDiff',$makeDiff);
  1270. }
  1271. #
  1272. # handle entry-based offsets
  1273. #
  1274. if ($entryBased) {
  1275. $debug and print "--> entry-based!\n";
  1276. # most of my entry-based samples have first value immediately
  1277. # after last IFD entry (ie. no padding or next IFD pointer)
  1278. $makeDiff = 0;
  1279. push @offsets, 4; # but some do have a next IFD pointer
  1280. # corrected entry-based offsets are relative to start of first entry
  1281. my $expected = 12 * Get16u($$dirInfo{DataPt}, $dirStart);
  1282. $diff = $$valBlkAdj{MIN} - $expected;
  1283. # set up directory to read values with entry-based offsets
  1284. # (ignore everything and set base to start of first entry)
  1285. $shift = $dataPos + $dirStart + 2;
  1286. $$dirInfo{Base} += $shift;
  1287. $$dirInfo{DataPos} -= $shift;
  1288. $$dirInfo{EntryBased} = 1;
  1289. $$dirInfo{Relative} = 1; # entry-based offsets are relative
  1290. delete $$dirInfo{FixBase}; # no automatic base fix
  1291. undef $fixBase unless $setBase;
  1292. }
  1293. #
  1294. # return without doing shift if offsets look OK
  1295. #
  1296. unless ($setBase) {
  1297. # don't try to fix offsets for whacky cameras
  1298. return $shift unless defined $makeDiff;
  1299. # normal value data starts 4 bytes after IFD, but allow 0 or 4...
  1300. return $shift if $diff == 0 or $diff == 4;
  1301. # also check for allowed make-specific differences
  1302. foreach (@offsets) {
  1303. return $shift if $diff == $_;
  1304. }
  1305. }
  1306. #
  1307. # apply the fix, or issue a warning
  1308. #
  1309. # use default padding of 4 bytes unless already specified
  1310. $makeDiff = 4 unless defined $makeDiff;
  1311. $fix = $makeDiff - $diff; # assume standard diff for this make
  1312. if ($$dirInfo{FixBase}) {
  1313. # set flag if offsets are relative (base is at or above directory start)
  1314. if ($dataPos - $fix + $dirStart <= 0) {
  1315. $$dirInfo{Relative} = (defined $relative) ? $relative : 1;
  1316. }
  1317. if ($setBase) {
  1318. $fixedBy = $fixBase;
  1319. $fix += $fixBase;
  1320. }
  1321. } elsif (defined $fixBase) {
  1322. $fix = $fixBase if $fixBase ne '';
  1323. $fixedBy = $fix;
  1324. } else {
  1325. # print warning unless difference looks reasonable
  1326. if ($diff < 0 or $diff > 16 or ($diff & 0x01)) {
  1327. $et->Warn("Possibly incorrect maker notes offsets (fix by $fix?)",1);
  1328. }
  1329. # don't do the fix (but we already adjusted base if entry-based)
  1330. return $shift;
  1331. }
  1332. if (defined $fixedBy) {
  1333. $et->Warn("Adjusted $dirName base by $fixedBy",1);
  1334. $$dirInfo{FixedBy} = $fixedBy;
  1335. }
  1336. $$dirInfo{Base} += $fix;
  1337. $$dirInfo{DataPos} -= $fix;
  1338. return $fix + $shift;
  1339. }
  1340. #------------------------------------------------------------------------------
  1341. # Find start of IFD in unknown maker notes
  1342. # Inputs: 0) reference to directory information
  1343. # Returns: offset to IFD on success, undefined otherwise
  1344. # - dirInfo may contain TagInfo reference for tag associated with directory
  1345. # - on success, updates DirStart, DirLen, Base and DataPos in dirInfo
  1346. # - also sets Relative flag in dirInfo if offsets are relative to IFD
  1347. # Note: Changes byte ordering!
  1348. sub LocateIFD($$)
  1349. {
  1350. my ($et, $dirInfo) = @_;
  1351. my $dataPt = $$dirInfo{DataPt};
  1352. my $dirStart = $$dirInfo{DirStart} || 0;
  1353. # (ignore MakerNotes DirLen since sometimes this is incorrect)
  1354. my $size = $$dirInfo{DataLen} - $dirStart;
  1355. my $dirLen = defined $$dirInfo{DirLen} ? $$dirInfo{DirLen} : $size;
  1356. my $tagInfo = $$dirInfo{TagInfo};
  1357. my $ifdOffsetPos;
  1358. # the IFD should be within the first 32 bytes
  1359. # (Kyocera sets the current record at 22 bytes)
  1360. my ($firstTry, $lastTry) = (0, 32);
  1361. # make sure Base and DataPos are defined
  1362. $$dirInfo{Base} or $$dirInfo{Base} = 0;
  1363. $$dirInfo{DataPos} or $$dirInfo{DataPos} = 0;
  1364. #
  1365. # use tag information (if provided) to determine directory location
  1366. #
  1367. if ($tagInfo and $$tagInfo{SubDirectory}) {
  1368. my $subdir = $$tagInfo{SubDirectory};
  1369. unless ($$subdir{ProcessProc} and
  1370. ($$subdir{ProcessProc} eq \&ProcessUnknown or
  1371. $$subdir{ProcessProc} eq \&ProcessUnknownOrPreview))
  1372. {
  1373. # look for the IFD at the "Start" specified in our SubDirectory information
  1374. my $valuePtr = $dirStart;
  1375. my $newStart = $dirStart;
  1376. if (defined $$subdir{Start}) {
  1377. #### eval Start ($valuePtr)
  1378. $newStart = eval($$subdir{Start});
  1379. }
  1380. if ($$subdir{Base}) {
  1381. # calculate subdirectory start relative to $base for eval
  1382. my $start = $newStart + $$dirInfo{DataPos};
  1383. my $base = $$dirInfo{Base} || 0;
  1384. #### eval Base ($start,$base)
  1385. my $baseShift = eval($$subdir{Base});
  1386. # shift directory base (note: we may do this again below
  1387. # if an OffsetPt is defined, but that doesn't matter since
  1388. # the base shift is relative to DataPos, which we set too)
  1389. $$dirInfo{Base} += $baseShift;
  1390. $$dirInfo{DataPos} -= $baseShift;
  1391. # this is a relative directory if Base depends on $start
  1392. if ($$subdir{Base} =~ /\$start\b/) {
  1393. $$dirInfo{Relative} = 1;
  1394. # hack to fix Leica quirk
  1395. if ($$subdir{ProcessProc} and $$subdir{ProcessProc} eq \&FixLeicaBase) {
  1396. my $oldStart = $$dirInfo{DirStart};
  1397. $$dirInfo{DirStart} = $newStart;
  1398. FixLeicaBase($et, $dirInfo);
  1399. $$dirInfo{DirStart} = $oldStart;
  1400. }
  1401. }
  1402. }
  1403. # add offset to the start of the directory if necessary
  1404. if ($$subdir{OffsetPt}) {
  1405. if ($$subdir{ByteOrder} =~ /^Little/i) {
  1406. SetByteOrder('II');
  1407. } elsif ($$subdir{ByteOrder} =~ /^Big/i) {
  1408. SetByteOrder('MM');
  1409. } else {
  1410. warn "Can't have variable byte ordering for SubDirectories using OffsetPt\n";
  1411. return undef;
  1412. }
  1413. #### eval OffsetPt ($valuePtr)
  1414. $ifdOffsetPos = eval($$subdir{OffsetPt}) - $dirStart;
  1415. }
  1416. # pinpoint position to look for this IFD
  1417. $firstTry = $lastTry = $newStart - $dirStart;
  1418. }
  1419. }
  1420. #
  1421. # scan for something that looks like an IFD
  1422. #
  1423. if ($dirLen >= 14 + $firstTry) { # minimum size for an IFD
  1424. my $offset;
  1425. IFD_TRY: for ($offset=$firstTry; $offset<=$lastTry; $offset+=2) {
  1426. last if $offset + 14 > $dirLen; # 14 bytes is minimum size for an IFD
  1427. my $pos = $dirStart + $offset;
  1428. #
  1429. # look for a standard TIFF header (Nikon uses it, others may as well),
  1430. #
  1431. if (SetByteOrder(substr($$dataPt, $pos, 2)) and
  1432. Get16u($dataPt, $pos + 2) == 0x2a)
  1433. {
  1434. $ifdOffsetPos = 4;
  1435. }
  1436. if (defined $ifdOffsetPos) {
  1437. # get pointer to IFD
  1438. my $ptr = Get32u($dataPt, $pos + $ifdOffsetPos);
  1439. if ($ptr >= $ifdOffsetPos + 4 and $ptr + $offset + 14 <= $dirLen) {
  1440. # shift directory start and shorten dirLen accordingly
  1441. $$dirInfo{DirStart} += $ptr + $offset;
  1442. $$dirInfo{DirLen} -= $ptr + $offset;
  1443. # shift pointer base to the start of the TIFF header
  1444. my $shift = $$dirInfo{DataPos} + $dirStart + $offset;
  1445. $$dirInfo{Base} += $shift;
  1446. $$dirInfo{DataPos} -= $shift;
  1447. $$dirInfo{Relative} = 1; # set "relative offsets" flag
  1448. return $ptr + $offset;
  1449. }
  1450. undef $ifdOffsetPos;
  1451. }
  1452. #
  1453. # look for a standard IFD (starts with 2-byte entry count)
  1454. #
  1455. my $num = Get16u($dataPt, $pos);
  1456. next unless $num;
  1457. # number of entries in an IFD should be between 1 and 255
  1458. if (!($num & 0xff)) {
  1459. # lower byte is zero -- byte order could be wrong
  1460. ToggleByteOrder();
  1461. $num >>= 8;
  1462. } elsif ($num & 0xff00) {
  1463. # upper byte isn't zero -- not an IFD
  1464. next;
  1465. }
  1466. my $bytesFromEnd = $size - ($offset + 2 + 12 * $num);
  1467. if ($bytesFromEnd < 4) {
  1468. next unless $bytesFromEnd == 2 or $bytesFromEnd == 0;
  1469. }
  1470. # do a quick validation of all format types
  1471. my $index;
  1472. for ($index=0; $index<$num; ++$index) {
  1473. my $entry = $pos + 2 + 12 * $index;
  1474. my $format = Get16u($dataPt, $entry+2);
  1475. my $count = Get32u($dataPt, $entry+4);
  1476. unless ($format) {
  1477. # patch for buggy Samsung NX200 JPEG MakerNotes entry count
  1478. if ($num == 23 and $index == 21 and $$et{Make} eq 'SAMSUNG') {
  1479. Set16u(21, $dataPt, $pos); # really 21 IFD entries!
  1480. $et->Warn('Fixed incorrect Makernote entry count', 1);
  1481. last;
  1482. }
  1483. # allow everything to be zero if not first entry
  1484. # because some manufacturers pad with null entries
  1485. next unless $count or $index == 0;
  1486. # patch for Canon EOS 40D firmware 1.0.4 bug: allow zero format for last entry
  1487. next if $index==$num-1 and $$et{Model}=~/EOS 40D/;
  1488. }
  1489. # patch for Sony cameras like the DSC-P10 that have invalid MakerNote entries
  1490. next if $num == 12 and $$et{Make} eq 'SONY' and $index >= 8;
  1491. # (would like to verify tag ID, but some manufactures don't
  1492. # sort entries in order of tag ID so we don't have much of
  1493. # a handle to verify this field)
  1494. # verify format
  1495. next IFD_TRY if $format < 1 or $format > 13;
  1496. # count must be reasonable (can't test for zero count because
  1497. # cameras like the 1DmkIII use this value)
  1498. next IFD_TRY if $count & 0xff000000;
  1499. # extra tests to avoid mis-identifying Samsung makernotes (GT-I9000, etc)
  1500. next unless $num == 1;
  1501. my $valueSize = $count * $Image::ExifTool::Exif::formatSize[$format];
  1502. if ($valueSize > 4) {
  1503. next IFD_TRY if $valueSize > $size;
  1504. my $valuePtr = Get32u($dataPt, $entry+8);
  1505. next IFD_TRY if $valuePtr > 0x10000;
  1506. }
  1507. }
  1508. $$dirInfo{DirStart} += $offset; # update directory start
  1509. $$dirInfo{DirLen} -= $offset;
  1510. return $offset; # success!!
  1511. }
  1512. }
  1513. return undef;
  1514. }
  1515. #------------------------------------------------------------------------------
  1516. # Fix base offset for Leica maker notes
  1517. # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
  1518. # Returns: 1 on success, and updates $dirInfo if necessary for new directory
  1519. sub FixLeicaBase($$;$)
  1520. {
  1521. my ($et, $dirInfo, $tagTablePtr) = @_;
  1522. my $dataPt = $$dirInfo{DataPt};
  1523. my $dirStart = $$dirInfo{DirStart} || 0;
  1524. # get hash of value block positions
  1525. my ($valBlock, $valBlkAdj) = GetValueBlocks($dataPt, $dirStart);
  1526. if (%$valBlock) {
  1527. # get sorted list of value offsets
  1528. my @valPtrs = sort { $a <=> $b } keys %$valBlock;
  1529. my $numEntries = Get16u($dataPt, $dirStart);
  1530. my $diff = $valPtrs[0] - ($numEntries * 12 + 4);
  1531. if ($diff > 8) {
  1532. $$dirInfo{Base} -= 8;
  1533. $$dirInfo{DataPos} += 8;
  1534. }
  1535. }
  1536. my $success = 1;
  1537. if ($tagTablePtr) {
  1538. $success = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr);
  1539. }
  1540. return $success;
  1541. }
  1542. #------------------------------------------------------------------------------
  1543. # Process Canon maker notes
  1544. # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
  1545. # Returns: 1 on success
  1546. sub ProcessCanon($$$)
  1547. {
  1548. my ($et, $dirInfo, $tagTablePtr) = @_;
  1549. # identify Canon MakerNote footer in HtmlDump
  1550. # (this code moved from FixBase so it also works for Adobe MakN in DNG images)
  1551. if ($$et{HTML_DUMP} and $$dirInfo{DirLen} > 8) {
  1552. my $dataPos = $$dirInfo{DataPos};
  1553. my $dirStart = $$dirInfo{DirStart} || 0;
  1554. my $footerPos = $dirStart + $$dirInfo{DirLen} - 8;
  1555. my $footer = substr(${$$dirInfo{DataPt}}, $footerPos, 8);
  1556. if ($footer =~ /^(II\x2a\0|MM\0\x2a)/ and substr($footer,0,2) eq GetByteOrder()) {
  1557. my $oldOffset = Get32u(\$footer, 4);
  1558. my $newOffset = $dirStart + $dataPos;
  1559. my $str = sprintf('Original maker note offset: 0x%.4x', $oldOffset);
  1560. if ($oldOffset != $newOffset) {
  1561. $str .= sprintf("\nCurrent maker note offset: 0x%.4x", $newOffset);
  1562. }
  1563. my $filePos = ($$dirInfo{Base} || 0) + $dataPos + $footerPos;
  1564. $et->HDump($filePos, 8, '[Canon MakerNotes footer]', $str);
  1565. }
  1566. }
  1567. # process as normal
  1568. return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr);
  1569. }
  1570. #------------------------------------------------------------------------------
  1571. # Process GE type 2 maker notes
  1572. # Inputs: 0) ExifTool object ref, 1) DirInfo ref, 2) tag table ref
  1573. # Returns: 1 on success
  1574. sub ProcessGE2($$$)
  1575. {
  1576. my ($et, $dirInfo, $tagTablePtr) = @_;
  1577. my $dataPt = $$dirInfo{DataPt} or return 0;
  1578. my $dirStart = $$dirInfo{DirStart} || 0;
  1579. # these maker notes are missing the IFD entry count, but they
  1580. # always have 25 entries, so write the entry count manually
  1581. Set16u(25, $dataPt, $dirStart);
  1582. return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr);
  1583. }
  1584. #------------------------------------------------------------------------------
  1585. # Process broken Kodak type 8b maker notes
  1586. # Inputs: 0) ExifTool object ref, 1) DirInfo ref, 2) tag table ref
  1587. # Returns: 1 on success
  1588. sub ProcessKodakPatch($$$)
  1589. {
  1590. my ($et, $dirInfo, $tagTablePtr) = @_;
  1591. my $dataPt = $$dirInfo{DataPt} or return 0;
  1592. my $dirStart = $$dirInfo{DirStart} || 0;
  1593. # these maker notes have 2 extra bytes after the entry count, so fix this
  1594. return 0 unless $$dirInfo{DirLen} > 2;
  1595. Set16u(Get16u($dataPt,$dirStart), $dataPt, $dirStart+2);
  1596. $$dirInfo{DirStart} += 2;
  1597. return Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr);
  1598. }
  1599. #------------------------------------------------------------------------------
  1600. # Process unknown maker notes or PreviewImage
  1601. # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
  1602. # Returns: 1 on success, and updates $dirInfo if necessary for new directory
  1603. sub ProcessUnknownOrPreview($$$)
  1604. {
  1605. my ($et, $dirInfo, $tagTablePtr) = @_;
  1606. my $dataPt = $$dirInfo{DataPt};
  1607. my $dirStart = $$dirInfo{DirStart};
  1608. my $dirLen = $$dirInfo{DirLen};
  1609. # check to see if this is a preview image
  1610. if ($dirLen > 6 and substr($$dataPt, $dirStart, 3) eq "\xff\xd8\xff") {
  1611. $et->VerboseDir('PreviewImage');
  1612. if ($$et{HTML_DUMP}) {
  1613. my $pos = $$dirInfo{DataPos} + $$dirInfo{Base} + $dirStart;
  1614. $et->HDump($pos, $dirLen, '(MakerNotes:PreviewImage data)', "Size: $dirLen bytes")
  1615. }
  1616. $et->FoundTag('PreviewImage', substr($$dataPt, $dirStart, $dirLen));
  1617. return 1;
  1618. }
  1619. return ProcessUnknown($et, $dirInfo, $tagTablePtr);
  1620. }
  1621. #------------------------------------------------------------------------------
  1622. # Write unknown maker notes or PreviewImage
  1623. # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
  1624. # Returns: directory data, '' to delete, or undef on error
  1625. sub WriteUnknownOrPreview($$$)
  1626. {
  1627. my ($et, $dirInfo, $tagTablePtr) = @_;
  1628. my $dataPt = $$dirInfo{DataPt};
  1629. my $dirStart = $$dirInfo{DirStart};
  1630. my $dirLen = $$dirInfo{DirLen};
  1631. my $newVal;
  1632. # check to see if this is a preview image
  1633. if ($dirLen > 6 and substr($$dataPt, $dirStart, 3) eq "\xff\xd8\xff") {
  1634. if ($$et{NEW_VALUE}{$Image::ExifTool::Extra{PreviewImage}}) {
  1635. # write or delete new preview (if deleted, it can't currently be added back again)
  1636. $newVal = $et->GetNewValue('PreviewImage') || '';
  1637. if ($et->Options('Verbose') > 1) {
  1638. $et->VerboseValue("- MakerNotes:PreviewImage", substr($$dataPt, $dirStart, $dirLen));
  1639. $et->VerboseValue("+ MakerNotes:PreviewImage", $newVal) if $newVal;
  1640. }
  1641. ++$$et{CHANGED};
  1642. } else {
  1643. $newVal = substr($$dataPt, $dirStart, $dirLen);
  1644. }
  1645. } else {
  1646. # rewrite MakerNote IFD
  1647. $newVal = Image::ExifTool::Exif::WriteExif($et, $dirInfo, $tagTablePtr);
  1648. }
  1649. return $newVal;
  1650. }
  1651. #------------------------------------------------------------------------------
  1652. # Process unknown maker notes assuming it is in EXIF IFD format
  1653. # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
  1654. # Returns: 1 on success, and updates $dirInfo if necessary for new directory
  1655. sub ProcessUnknown($$$)
  1656. {
  1657. my ($et, $dirInfo, $tagTablePtr) = @_;
  1658. my $success = 0;
  1659. my $loc = LocateIFD($et, $dirInfo);
  1660. if (defined $loc) {
  1661. $$et{UnknownByteOrder} = GetByteOrder();
  1662. if ($et->Options('Verbose') > 1) {
  1663. my $out = $et->Options('TextOut');
  1664. my $indent = $$et{INDENT};
  1665. $indent =~ s/\| $/ /;
  1666. printf $out "${indent}Found IFD at offset 0x%.4x in maker notes:\n",
  1667. $$dirInfo{DirStart} + $$dirInfo{DataPos} + $$dirInfo{Base};
  1668. }
  1669. $success = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr);
  1670. } else {
  1671. $$et{UnknownByteOrder} = ''; # indicates we tried but didn't set byte order
  1672. $et->Warn("Unrecognized $$dirInfo{DirName}", 1);
  1673. }
  1674. return $success;
  1675. }
  1676. 1; # end
  1677. __END__
  1678. =head1 NAME
  1679. Image::ExifTool::MakerNotes - Read and write EXIF maker notes
  1680. =head1 SYNOPSIS
  1681. This module is required by Image::ExifTool.
  1682. =head1 DESCRIPTION
  1683. This module contains definitions required by Image::ExifTool to interpret
  1684. maker notes in EXIF information.
  1685. =head1 AUTHOR
  1686. Copyright 2003-2016, Phil Harvey (phil at owl.phy.queensu.ca)
  1687. This library is free software; you can redistribute it and/or modify it
  1688. under the same terms as Perl itself.
  1689. =head1 SEE ALSO
  1690. L<Image::ExifTool::TagNames(3pm)|Image::ExifTool::TagNames>,
  1691. L<Image::ExifTool(3pm)|Image::ExifTool>
  1692. =cut