exiftool_vendored 9.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (864) hide show
  1. checksums.yaml +15 -0
  2. data/bin/Image-ExifTool-9.33/Changes +6241 -0
  3. data/bin/Image-ExifTool-9.33/MANIFEST +859 -0
  4. data/bin/Image-ExifTool-9.33/META.yml +27 -0
  5. data/bin/Image-ExifTool-9.33/Makefile.PL +41 -0
  6. data/bin/Image-ExifTool-9.33/README +227 -0
  7. data/bin/Image-ExifTool-9.33/arg_files/exif2iptc.args +24 -0
  8. data/bin/Image-ExifTool-9.33/arg_files/exif2xmp.args +38 -0
  9. data/bin/Image-ExifTool-9.33/arg_files/gps2xmp.args +20 -0
  10. data/bin/Image-ExifTool-9.33/arg_files/iptc2exif.args +17 -0
  11. data/bin/Image-ExifTool-9.33/arg_files/iptc2xmp.args +53 -0
  12. data/bin/Image-ExifTool-9.33/arg_files/iptcCore.args +172 -0
  13. data/bin/Image-ExifTool-9.33/arg_files/pdf2xmp.args +23 -0
  14. data/bin/Image-ExifTool-9.33/arg_files/xmp2exif.args +39 -0
  15. data/bin/Image-ExifTool-9.33/arg_files/xmp2gps.args +24 -0
  16. data/bin/Image-ExifTool-9.33/arg_files/xmp2iptc.args +62 -0
  17. data/bin/Image-ExifTool-9.33/arg_files/xmp2pdf.args +23 -0
  18. data/bin/Image-ExifTool-9.33/config_files/ExifTool_config +299 -0
  19. data/bin/Image-ExifTool-9.33/config_files/convert_regions.config +81 -0
  20. data/bin/Image-ExifTool-9.33/exiftool +5715 -0
  21. data/bin/Image-ExifTool-9.33/fmt_files/gpx.fmt +29 -0
  22. data/bin/Image-ExifTool-9.33/fmt_files/gpx_wpt.fmt +33 -0
  23. data/bin/Image-ExifTool-9.33/fmt_files/kml.fmt +53 -0
  24. data/bin/Image-ExifTool-9.33/html/ExifTool.html +1959 -0
  25. data/bin/Image-ExifTool-9.33/html/MIE1.1-20070121.pdf +0 -0
  26. data/bin/Image-ExifTool-9.33/html/Shift.html +173 -0
  27. data/bin/Image-ExifTool-9.33/html/TagNames/AFCP.html +53 -0
  28. data/bin/Image-ExifTool-9.33/html/TagNames/AIFF.html +146 -0
  29. data/bin/Image-ExifTool-9.33/html/TagNames/APE.html +149 -0
  30. data/bin/Image-ExifTool-9.33/html/TagNames/APP12.html +188 -0
  31. data/bin/Image-ExifTool-9.33/html/TagNames/ASF.html +1066 -0
  32. data/bin/Image-ExifTool-9.33/html/TagNames/BMP.html +110 -0
  33. data/bin/Image-ExifTool-9.33/html/TagNames/Canon.html +8062 -0
  34. data/bin/Image-ExifTool-9.33/html/TagNames/CanonCustom.html +2044 -0
  35. data/bin/Image-ExifTool-9.33/html/TagNames/CanonRaw.html +561 -0
  36. data/bin/Image-ExifTool-9.33/html/TagNames/CanonVRD.html +1222 -0
  37. data/bin/Image-ExifTool-9.33/html/TagNames/Casio.html +1569 -0
  38. data/bin/Image-ExifTool-9.33/html/TagNames/Composite.html +665 -0
  39. data/bin/Image-ExifTool-9.33/html/TagNames/DICOM.html +15762 -0
  40. data/bin/Image-ExifTool-9.33/html/TagNames/DNG.html +273 -0
  41. data/bin/Image-ExifTool-9.33/html/TagNames/DV.html +75 -0
  42. data/bin/Image-ExifTool-9.33/html/TagNames/DarwinCore.html +1445 -0
  43. data/bin/Image-ExifTool-9.33/html/TagNames/DjVu.html +313 -0
  44. data/bin/Image-ExifTool-9.33/html/TagNames/EXE.html +697 -0
  45. data/bin/Image-ExifTool-9.33/html/TagNames/EXIF.html +3244 -0
  46. data/bin/Image-ExifTool-9.33/html/TagNames/Extra.html +301 -0
  47. data/bin/Image-ExifTool-9.33/html/TagNames/FLAC.html +183 -0
  48. data/bin/Image-ExifTool-9.33/html/TagNames/FLIR.html +931 -0
  49. data/bin/Image-ExifTool-9.33/html/TagNames/Flash.html +419 -0
  50. data/bin/Image-ExifTool-9.33/html/TagNames/FlashPix.html +1435 -0
  51. data/bin/Image-ExifTool-9.33/html/TagNames/Font.html +485 -0
  52. data/bin/Image-ExifTool-9.33/html/TagNames/FotoStation.html +103 -0
  53. data/bin/Image-ExifTool-9.33/html/TagNames/FujiFilm.html +637 -0
  54. data/bin/Image-ExifTool-9.33/html/TagNames/GE.html +40 -0
  55. data/bin/Image-ExifTool-9.33/html/TagNames/GIF.html +116 -0
  56. data/bin/Image-ExifTool-9.33/html/TagNames/GIMP.html +140 -0
  57. data/bin/Image-ExifTool-9.33/html/TagNames/GPS.html +222 -0
  58. data/bin/Image-ExifTool-9.33/html/TagNames/GeoTiff.html +2177 -0
  59. data/bin/Image-ExifTool-9.33/html/TagNames/H264.html +393 -0
  60. data/bin/Image-ExifTool-9.33/html/TagNames/HP.html +155 -0
  61. data/bin/Image-ExifTool-9.33/html/TagNames/HTML.html +666 -0
  62. data/bin/Image-ExifTool-9.33/html/TagNames/ICC_Profile.html +710 -0
  63. data/bin/Image-ExifTool-9.33/html/TagNames/ID3.html +1473 -0
  64. data/bin/Image-ExifTool-9.33/html/TagNames/IPTC.html +895 -0
  65. data/bin/Image-ExifTool-9.33/html/TagNames/ITC.html +90 -0
  66. data/bin/Image-ExifTool-9.33/html/TagNames/JFIF.html +61 -0
  67. data/bin/Image-ExifTool-9.33/html/TagNames/JPEG.html +523 -0
  68. data/bin/Image-ExifTool-9.33/html/TagNames/JVC.html +56 -0
  69. data/bin/Image-ExifTool-9.33/html/TagNames/Jpeg2000.html +464 -0
  70. data/bin/Image-ExifTool-9.33/html/TagNames/Kodak.html +1759 -0
  71. data/bin/Image-ExifTool-9.33/html/TagNames/KyoceraRaw.html +92 -0
  72. data/bin/Image-ExifTool-9.33/html/TagNames/LNK.html +478 -0
  73. data/bin/Image-ExifTool-9.33/html/TagNames/Leaf.html +870 -0
  74. data/bin/Image-ExifTool-9.33/html/TagNames/M2TS.html +133 -0
  75. data/bin/Image-ExifTool-9.33/html/TagNames/MIE.html +1026 -0
  76. data/bin/Image-ExifTool-9.33/html/TagNames/MIFF.html +196 -0
  77. data/bin/Image-ExifTool-9.33/html/TagNames/MNG.html +847 -0
  78. data/bin/Image-ExifTool-9.33/html/TagNames/MPC.html +97 -0
  79. data/bin/Image-ExifTool-9.33/html/TagNames/MPEG.html +249 -0
  80. data/bin/Image-ExifTool-9.33/html/TagNames/MPF.html +199 -0
  81. data/bin/Image-ExifTool-9.33/html/TagNames/MWG.html +563 -0
  82. data/bin/Image-ExifTool-9.33/html/TagNames/MXF.html +6673 -0
  83. data/bin/Image-ExifTool-9.33/html/TagNames/Matroska.html +1069 -0
  84. data/bin/Image-ExifTool-9.33/html/TagNames/Microsoft.html +2066 -0
  85. data/bin/Image-ExifTool-9.33/html/TagNames/Minolta.html +2555 -0
  86. data/bin/Image-ExifTool-9.33/html/TagNames/MinoltaRaw.html +326 -0
  87. data/bin/Image-ExifTool-9.33/html/TagNames/Nikon.html +4467 -0
  88. data/bin/Image-ExifTool-9.33/html/TagNames/NikonCapture.html +776 -0
  89. data/bin/Image-ExifTool-9.33/html/TagNames/NikonCustom.html +3835 -0
  90. data/bin/Image-ExifTool-9.33/html/TagNames/OOXML.html +280 -0
  91. data/bin/Image-ExifTool-9.33/html/TagNames/Ogg.html +44 -0
  92. data/bin/Image-ExifTool-9.33/html/TagNames/Olympus.html +3386 -0
  93. data/bin/Image-ExifTool-9.33/html/TagNames/OpenEXR.html +222 -0
  94. data/bin/Image-ExifTool-9.33/html/TagNames/PDF.html +745 -0
  95. data/bin/Image-ExifTool-9.33/html/TagNames/PGF.html +80 -0
  96. data/bin/Image-ExifTool-9.33/html/TagNames/PICT.html +753 -0
  97. data/bin/Image-ExifTool-9.33/html/TagNames/PLIST.html +86 -0
  98. data/bin/Image-ExifTool-9.33/html/TagNames/PNG.html +515 -0
  99. data/bin/Image-ExifTool-9.33/html/TagNames/PSP.html +160 -0
  100. data/bin/Image-ExifTool-9.33/html/TagNames/Panasonic.html +1452 -0
  101. data/bin/Image-ExifTool-9.33/html/TagNames/PanasonicRaw.html +214 -0
  102. data/bin/Image-ExifTool-9.33/html/TagNames/Pentax.html +4332 -0
  103. data/bin/Image-ExifTool-9.33/html/TagNames/PhaseOne.html +258 -0
  104. data/bin/Image-ExifTool-9.33/html/TagNames/PhotoCD.html +402 -0
  105. data/bin/Image-ExifTool-9.33/html/TagNames/PhotoMechanic.html +196 -0
  106. data/bin/Image-ExifTool-9.33/html/TagNames/Photoshop.html +555 -0
  107. data/bin/Image-ExifTool-9.33/html/TagNames/PostScript.html +125 -0
  108. data/bin/Image-ExifTool-9.33/html/TagNames/PrintIM.html +31 -0
  109. data/bin/Image-ExifTool-9.33/html/TagNames/Qualcomm.html +4778 -0
  110. data/bin/Image-ExifTool-9.33/html/TagNames/QuickTime.html +3104 -0
  111. data/bin/Image-ExifTool-9.33/html/TagNames/RIFF.html +1164 -0
  112. data/bin/Image-ExifTool-9.33/html/TagNames/RSRC.html +74 -0
  113. data/bin/Image-ExifTool-9.33/html/TagNames/RTF.html +150 -0
  114. data/bin/Image-ExifTool-9.33/html/TagNames/Radiance.html +87 -0
  115. data/bin/Image-ExifTool-9.33/html/TagNames/Rawzor.html +45 -0
  116. data/bin/Image-ExifTool-9.33/html/TagNames/Real.html +780 -0
  117. data/bin/Image-ExifTool-9.33/html/TagNames/Reconyx.html +132 -0
  118. data/bin/Image-ExifTool-9.33/html/TagNames/Ricoh.html +456 -0
  119. data/bin/Image-ExifTool-9.33/html/TagNames/Samsung.html +419 -0
  120. data/bin/Image-ExifTool-9.33/html/TagNames/Sanyo.html +366 -0
  121. data/bin/Image-ExifTool-9.33/html/TagNames/Shortcuts.html +237 -0
  122. data/bin/Image-ExifTool-9.33/html/TagNames/Sigma.html +372 -0
  123. data/bin/Image-ExifTool-9.33/html/TagNames/SigmaRaw.html +403 -0
  124. data/bin/Image-ExifTool-9.33/html/TagNames/Sony.html +4279 -0
  125. data/bin/Image-ExifTool-9.33/html/TagNames/SonyIDC.html +267 -0
  126. data/bin/Image-ExifTool-9.33/html/TagNames/Stim.html +200 -0
  127. data/bin/Image-ExifTool-9.33/html/TagNames/Theora.html +102 -0
  128. data/bin/Image-ExifTool-9.33/html/TagNames/Unknown.html +31 -0
  129. data/bin/Image-ExifTool-9.33/html/TagNames/Vorbis.html +228 -0
  130. data/bin/Image-ExifTool-9.33/html/TagNames/XMP.html +7234 -0
  131. data/bin/Image-ExifTool-9.33/html/TagNames/ZIP.html +204 -0
  132. data/bin/Image-ExifTool-9.33/html/TagNames/iWork.html +49 -0
  133. data/bin/Image-ExifTool-9.33/html/TagNames/index.html +192 -0
  134. data/bin/Image-ExifTool-9.33/html/TagNames/style.css +31 -0
  135. data/bin/Image-ExifTool-9.33/html/ancient_history.html +6727 -0
  136. data/bin/Image-ExifTool-9.33/html/canon_raw.html +366 -0
  137. data/bin/Image-ExifTool-9.33/html/commentary.html +319 -0
  138. data/bin/Image-ExifTool-9.33/html/config.html +312 -0
  139. data/bin/Image-ExifTool-9.33/html/data_members.html +265 -0
  140. data/bin/Image-ExifTool-9.33/html/exiftool_pod.html +2338 -0
  141. data/bin/Image-ExifTool-9.33/html/faq.html +1434 -0
  142. data/bin/Image-ExifTool-9.33/html/filename.html +281 -0
  143. data/bin/Image-ExifTool-9.33/html/geotag.html +642 -0
  144. data/bin/Image-ExifTool-9.33/html/history.html +358 -0
  145. data/bin/Image-ExifTool-9.33/html/htmldump.html +732 -0
  146. data/bin/Image-ExifTool-9.33/html/idiosyncracies.html +251 -0
  147. data/bin/Image-ExifTool-9.33/html/index.html +1271 -0
  148. data/bin/Image-ExifTool-9.33/html/install.html +239 -0
  149. data/bin/Image-ExifTool-9.33/html/metafiles.html +266 -0
  150. data/bin/Image-ExifTool-9.33/html/overview.png +0 -0
  151. data/bin/Image-ExifTool-9.33/html/standards.html +277 -0
  152. data/bin/Image-ExifTool-9.33/html/struct.html +342 -0
  153. data/bin/Image-ExifTool-9.33/html/style.css +31 -0
  154. data/bin/Image-ExifTool-9.33/html/under.html +124 -0
  155. data/bin/Image-ExifTool-9.33/html/verbose.html +195 -0
  156. data/bin/Image-ExifTool-9.33/html/writing.html +239 -0
  157. data/bin/Image-ExifTool-9.33/lib/File/RandomAccess.pm +378 -0
  158. data/bin/Image-ExifTool-9.33/lib/File/RandomAccess.pod +231 -0
  159. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool.pm +6815 -0
  160. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool.pod +2385 -0
  161. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/AES.pm +501 -0
  162. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/AFCP.pm +284 -0
  163. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/AIFF.pm +271 -0
  164. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/APE.pm +262 -0
  165. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/APP12.pm +322 -0
  166. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/ASF.pm +884 -0
  167. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/BMP.pm +179 -0
  168. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/BZZ.pm +472 -0
  169. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/BigTIFF.pm +282 -0
  170. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/BuildTagLookup.pm +2400 -0
  171. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Canon.pm +7794 -0
  172. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/CanonCustom.pm +2523 -0
  173. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/CanonRaw.pm +931 -0
  174. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/CanonVRD.pm +1481 -0
  175. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/CaptureOne.pm +235 -0
  176. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Casio.pm +2013 -0
  177. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset.pm +396 -0
  178. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Arabic.pm +39 -0
  179. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Baltic.pm +35 -0
  180. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Cyrillic.pm +45 -0
  181. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Greek.pm +40 -0
  182. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Hebrew.pm +36 -0
  183. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/JIS.pm +1735 -0
  184. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Latin.pm +24 -0
  185. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Latin2.pm +36 -0
  186. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacArabic.pm +47 -0
  187. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacChineseCN.pm +2088 -0
  188. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacChineseTW.pm +3623 -0
  189. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacCroatian.pm +43 -0
  190. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacCyrillic.pm +47 -0
  191. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacGreek.pm +45 -0
  192. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacHebrew.pm +47 -0
  193. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacIceland.pm +42 -0
  194. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacJapanese.pm +1933 -0
  195. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacKorean.pm +2720 -0
  196. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacLatin2.pm +44 -0
  197. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacRSymbol.pm +2087 -0
  198. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacRoman.pm +42 -0
  199. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacRomanian.pm +42 -0
  200. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacThai.pm +49 -0
  201. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/MacTurkish.pm +42 -0
  202. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/PDFDoc.pm +28 -0
  203. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/ShiftJIS.pm +1835 -0
  204. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Symbol.pm +54 -0
  205. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Thai.pm +41 -0
  206. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Turkish.pm +25 -0
  207. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Charset/Vietnam.pm +27 -0
  208. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/DICOM.pm +3835 -0
  209. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/DNG.pm +835 -0
  210. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/DV.pm +319 -0
  211. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/DarwinCore.pm +317 -0
  212. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/DjVu.pm +376 -0
  213. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/EXE.pm +1228 -0
  214. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Exif.pm +4542 -0
  215. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/FLAC.pm +296 -0
  216. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/FLIR.pm +972 -0
  217. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Fixup.pm +354 -0
  218. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Flash.pm +755 -0
  219. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/FlashPix.pm +1882 -0
  220. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Font.pm +643 -0
  221. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/FotoStation.pm +258 -0
  222. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/FujiFilm.pm +1020 -0
  223. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/GE.pm +80 -0
  224. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/GIF.pm +542 -0
  225. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/GIMP.pm +258 -0
  226. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/GPS.pm +511 -0
  227. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/GeoTiff.pm +2187 -0
  228. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Geotag.pm +1173 -0
  229. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/H264.pm +1102 -0
  230. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/HP.pm +262 -0
  231. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/HTML.pm +576 -0
  232. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/HtmlDump.pm +895 -0
  233. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/ICC_Profile.pm +999 -0
  234. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/ID3.pm +1532 -0
  235. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/IPTC.pm +1244 -0
  236. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/ITC.pm +215 -0
  237. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Import.pm +308 -0
  238. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/InDesign.pm +277 -0
  239. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/JPEG.pm +588 -0
  240. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/JPEGDigest.pm +2511 -0
  241. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/JVC.pm +130 -0
  242. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Jpeg2000.pm +881 -0
  243. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Kodak.pm +2014 -0
  244. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/KyoceraRaw.pm +173 -0
  245. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/LNK.pm +723 -0
  246. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/cs.pm +1586 -0
  247. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/de.pm +7356 -0
  248. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/en_ca.pm +557 -0
  249. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/en_gb.pm +572 -0
  250. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/es.pm +4016 -0
  251. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/fi.pm +2856 -0
  252. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/fr.pm +4720 -0
  253. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/it.pm +7917 -0
  254. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/ja.pm +5815 -0
  255. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/ko.pm +2332 -0
  256. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/nl.pm +3220 -0
  257. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/pl.pm +1140 -0
  258. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/ru.pm +769 -0
  259. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/sv.pm +639 -0
  260. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/tr.pm +544 -0
  261. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/zh_cn.pm +1329 -0
  262. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Lang/zh_tw.pm +802 -0
  263. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Leaf.pm +515 -0
  264. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/M2TS.pm +729 -0
  265. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MIE.pm +2561 -0
  266. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MIEUnits.pod +377 -0
  267. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MIFF.pm +279 -0
  268. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MNG.pm +684 -0
  269. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MPC.pm +156 -0
  270. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MPEG.pm +736 -0
  271. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MPF.pm +289 -0
  272. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MWG.pm +736 -0
  273. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MXF.pm +3032 -0
  274. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MakerNotes.pm +1573 -0
  275. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Matroska.pm +891 -0
  276. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Microsoft.pm +879 -0
  277. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Minolta.pm +2833 -0
  278. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/MinoltaRaw.pm +534 -0
  279. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Nikon.pm +6116 -0
  280. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/NikonCapture.pm +911 -0
  281. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/NikonCustom.pm +4405 -0
  282. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/OOXML.pm +409 -0
  283. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Ogg.pm +237 -0
  284. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Olympus.pm +3582 -0
  285. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/OpenEXR.pm +324 -0
  286. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PDF.pm +2327 -0
  287. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PGF.pm +143 -0
  288. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PICT.pm +1260 -0
  289. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PLIST.pm +449 -0
  290. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PNG.pm +1100 -0
  291. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PPM.pm +169 -0
  292. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PSP.pm +305 -0
  293. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Panasonic.pm +1995 -0
  294. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PanasonicRaw.pm +535 -0
  295. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Pentax.pm +5489 -0
  296. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PhaseOne.pm +557 -0
  297. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PhotoCD.pm +507 -0
  298. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PhotoMechanic.pm +256 -0
  299. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Photoshop.pm +629 -0
  300. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PostScript.pm +693 -0
  301. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/PrintIM.pm +125 -0
  302. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Qualcomm.pm +1344 -0
  303. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/QuickTime.pm +3519 -0
  304. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/README +944 -0
  305. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/RIFF.pm +1322 -0
  306. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/RSRC.pm +241 -0
  307. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/RTF.pm +383 -0
  308. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Radiance.pm +144 -0
  309. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Rawzor.pm +190 -0
  310. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Real.pm +736 -0
  311. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Reconyx.pm +190 -0
  312. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Ricoh.pm +741 -0
  313. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Samsung.pm +820 -0
  314. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Sanyo.pm +439 -0
  315. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Shift.pl +594 -0
  316. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Shortcuts.pm +291 -0
  317. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Sigma.pm +574 -0
  318. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/SigmaRaw.pm +649 -0
  319. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Sony.pm +5722 -0
  320. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/SonyIDC.pm +330 -0
  321. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Stim.pm +196 -0
  322. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/TagInfoXML.pm +792 -0
  323. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/TagLookup.pm +8005 -0
  324. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/TagNames.pod +25950 -0
  325. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Theora.pm +145 -0
  326. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Unknown.pm +66 -0
  327. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Vorbis.pm +237 -0
  328. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/WriteCanonRaw.pl +637 -0
  329. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/WriteExif.pl +3674 -0
  330. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/WriteIPTC.pl +702 -0
  331. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/WritePDF.pl +759 -0
  332. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/WritePNG.pl +330 -0
  333. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/WritePhotoshop.pl +266 -0
  334. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/WritePostScript.pl +777 -0
  335. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/WriteXMP.pl +1318 -0
  336. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/Writer.pl +5779 -0
  337. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/XMP.pm +3634 -0
  338. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/XMP2.pl +1298 -0
  339. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/XMPStruct.pl +813 -0
  340. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/ZIP.pm +623 -0
  341. data/bin/Image-ExifTool-9.33/lib/Image/ExifTool/iWork.pm +223 -0
  342. data/bin/Image-ExifTool-9.33/perl-Image-ExifTool.spec +104 -0
  343. data/bin/Image-ExifTool-9.33/t/AFCP.t +44 -0
  344. data/bin/Image-ExifTool-9.33/t/AFCP_2.out +37 -0
  345. data/bin/Image-ExifTool-9.33/t/AFCP_3.out +20 -0
  346. data/bin/Image-ExifTool-9.33/t/AIFF.t +28 -0
  347. data/bin/Image-ExifTool-9.33/t/AIFF_2.out +31 -0
  348. data/bin/Image-ExifTool-9.33/t/APE.t +38 -0
  349. data/bin/Image-ExifTool-9.33/t/APE_2.out +28 -0
  350. data/bin/Image-ExifTool-9.33/t/APE_3.out +57 -0
  351. data/bin/Image-ExifTool-9.33/t/ASF.t +28 -0
  352. data/bin/Image-ExifTool-9.33/t/ASF_2.out +54 -0
  353. data/bin/Image-ExifTool-9.33/t/BMP.t +28 -0
  354. data/bin/Image-ExifTool-9.33/t/BMP_2.out +21 -0
  355. data/bin/Image-ExifTool-9.33/t/BigTIFF.t +28 -0
  356. data/bin/Image-ExifTool-9.33/t/BigTIFF_2.out +19 -0
  357. data/bin/Image-ExifTool-9.33/t/Canon.t +41 -0
  358. data/bin/Image-ExifTool-9.33/t/CanonRaw.t +126 -0
  359. data/bin/Image-ExifTool-9.33/t/CanonRaw_2.out +165 -0
  360. data/bin/Image-ExifTool-9.33/t/CanonRaw_4.out +217 -0
  361. data/bin/Image-ExifTool-9.33/t/CanonRaw_5.out +207 -0
  362. data/bin/Image-ExifTool-9.33/t/CanonRaw_6.out +231 -0
  363. data/bin/Image-ExifTool-9.33/t/CanonRaw_7.out +247 -0
  364. data/bin/Image-ExifTool-9.33/t/CanonVRD.t +129 -0
  365. data/bin/Image-ExifTool-9.33/t/CanonVRD_11.out +118 -0
  366. data/bin/Image-ExifTool-9.33/t/CanonVRD_12.out +12 -0
  367. data/bin/Image-ExifTool-9.33/t/CanonVRD_2.out +116 -0
  368. data/bin/Image-ExifTool-9.33/t/CanonVRD_3.out +116 -0
  369. data/bin/Image-ExifTool-9.33/t/CanonVRD_4.out +2 -0
  370. data/bin/Image-ExifTool-9.33/t/CanonVRD_5.out +3 -0
  371. data/bin/Image-ExifTool-9.33/t/CanonVRD_6.out +3 -0
  372. data/bin/Image-ExifTool-9.33/t/CanonVRD_7.out +2 -0
  373. data/bin/Image-ExifTool-9.33/t/CanonVRD_8.out +2 -0
  374. data/bin/Image-ExifTool-9.33/t/CanonVRD_9.out +1 -0
  375. data/bin/Image-ExifTool-9.33/t/Canon_2.out +350 -0
  376. data/bin/Image-ExifTool-9.33/t/Canon_3.out +3 -0
  377. data/bin/Image-ExifTool-9.33/t/Casio.t +54 -0
  378. data/bin/Image-ExifTool-9.33/t/Casio_2.out +70 -0
  379. data/bin/Image-ExifTool-9.33/t/Casio_3.out +100 -0
  380. data/bin/Image-ExifTool-9.33/t/Casio_4.out +26 -0
  381. data/bin/Image-ExifTool-9.33/t/Casio_5.out +78 -0
  382. data/bin/Image-ExifTool-9.33/t/Casio_6.out +115 -0
  383. data/bin/Image-ExifTool-9.33/t/DICOM.t +28 -0
  384. data/bin/Image-ExifTool-9.33/t/DICOM_2.out +108 -0
  385. data/bin/Image-ExifTool-9.33/t/DNG.t +39 -0
  386. data/bin/Image-ExifTool-9.33/t/DNG_2.out +326 -0
  387. data/bin/Image-ExifTool-9.33/t/DNG_3.out +4 -0
  388. data/bin/Image-ExifTool-9.33/t/DV.t +27 -0
  389. data/bin/Image-ExifTool-9.33/t/DV_2.out +24 -0
  390. data/bin/Image-ExifTool-9.33/t/DjVu.t +28 -0
  391. data/bin/Image-ExifTool-9.33/t/DjVu_2.out +44 -0
  392. data/bin/Image-ExifTool-9.33/t/EXE.t +31 -0
  393. data/bin/Image-ExifTool-9.33/t/EXE_2.out +40 -0
  394. data/bin/Image-ExifTool-9.33/t/EXE_3.out +15 -0
  395. data/bin/Image-ExifTool-9.33/t/EXE_4.out +14 -0
  396. data/bin/Image-ExifTool-9.33/t/ExifTool.t +284 -0
  397. data/bin/Image-ExifTool-9.33/t/ExifTool_16.out +180 -0
  398. data/bin/Image-ExifTool-9.33/t/ExifTool_17.out +594 -0
  399. data/bin/Image-ExifTool-9.33/t/ExifTool_2.out +399 -0
  400. data/bin/Image-ExifTool-9.33/t/ExifTool_20.out +1 -0
  401. data/bin/Image-ExifTool-9.33/t/ExifTool_21.out +1 -0
  402. data/bin/Image-ExifTool-9.33/t/ExifTool_22.out +1 -0
  403. data/bin/Image-ExifTool-9.33/t/ExifTool_23.out +6 -0
  404. data/bin/Image-ExifTool-9.33/t/ExifTool_24.out +3 -0
  405. data/bin/Image-ExifTool-9.33/t/ExifTool_25.out +13 -0
  406. data/bin/Image-ExifTool-9.33/t/ExifTool_26.out +12 -0
  407. data/bin/Image-ExifTool-9.33/t/ExifTool_3.out +87 -0
  408. data/bin/Image-ExifTool-9.33/t/ExifTool_4.out +41 -0
  409. data/bin/Image-ExifTool-9.33/t/ExifTool_5.out +6 -0
  410. data/bin/Image-ExifTool-9.33/t/ExifTool_6.out +68 -0
  411. data/bin/Image-ExifTool-9.33/t/ExifTool_7.out +125 -0
  412. data/bin/Image-ExifTool-9.33/t/ExifTool_8.out +125 -0
  413. data/bin/Image-ExifTool-9.33/t/ExifTool_9.out +33 -0
  414. data/bin/Image-ExifTool-9.33/t/FLAC.t +37 -0
  415. data/bin/Image-ExifTool-9.33/t/FLAC_2.out +25 -0
  416. data/bin/Image-ExifTool-9.33/t/FLAC_3.out +19 -0
  417. data/bin/Image-ExifTool-9.33/t/FLIR.t +30 -0
  418. data/bin/Image-ExifTool-9.33/t/FLIR_2.out +104 -0
  419. data/bin/Image-ExifTool-9.33/t/FLIR_3.out +47 -0
  420. data/bin/Image-ExifTool-9.33/t/Flash.t +37 -0
  421. data/bin/Image-ExifTool-9.33/t/FlashPix.t +30 -0
  422. data/bin/Image-ExifTool-9.33/t/FlashPix_2.out +48 -0
  423. data/bin/Image-ExifTool-9.33/t/Flash_2.out +20 -0
  424. data/bin/Image-ExifTool-9.33/t/Flash_3.out +53 -0
  425. data/bin/Image-ExifTool-9.33/t/Font.t +30 -0
  426. data/bin/Image-ExifTool-9.33/t/Font_2.out +23 -0
  427. data/bin/Image-ExifTool-9.33/t/Font_3.out +35 -0
  428. data/bin/Image-ExifTool-9.33/t/Font_4.out +26 -0
  429. data/bin/Image-ExifTool-9.33/t/Font_5.out +26 -0
  430. data/bin/Image-ExifTool-9.33/t/Font_6.out +36 -0
  431. data/bin/Image-ExifTool-9.33/t/Font_7.out +36 -0
  432. data/bin/Image-ExifTool-9.33/t/FotoStation.t +38 -0
  433. data/bin/Image-ExifTool-9.33/t/FotoStation_2.out +39 -0
  434. data/bin/Image-ExifTool-9.33/t/FotoStation_3.out +3 -0
  435. data/bin/Image-ExifTool-9.33/t/FujiFilm.t +78 -0
  436. data/bin/Image-ExifTool-9.33/t/FujiFilm_2.out +87 -0
  437. data/bin/Image-ExifTool-9.33/t/FujiFilm_3.out +88 -0
  438. data/bin/Image-ExifTool-9.33/t/FujiFilm_4.out +117 -0
  439. data/bin/Image-ExifTool-9.33/t/FujiFilm_5.out +1 -0
  440. data/bin/Image-ExifTool-9.33/t/GE.t +46 -0
  441. data/bin/Image-ExifTool-9.33/t/GE_2.out +84 -0
  442. data/bin/Image-ExifTool-9.33/t/GE_3.out +84 -0
  443. data/bin/Image-ExifTool-9.33/t/GIF.t +83 -0
  444. data/bin/Image-ExifTool-9.33/t/GIF_2.out +40 -0
  445. data/bin/Image-ExifTool-9.33/t/GIF_3.out +41 -0
  446. data/bin/Image-ExifTool-9.33/t/GIF_4.out +16 -0
  447. data/bin/Image-ExifTool-9.33/t/GIMP.t +27 -0
  448. data/bin/Image-ExifTool-9.33/t/GIMP_2.out +63 -0
  449. data/bin/Image-ExifTool-9.33/t/GPS.t +42 -0
  450. data/bin/Image-ExifTool-9.33/t/GPS_2.out +94 -0
  451. data/bin/Image-ExifTool-9.33/t/GPS_3.out +96 -0
  452. data/bin/Image-ExifTool-9.33/t/GeoTiff.t +36 -0
  453. data/bin/Image-ExifTool-9.33/t/GeoTiff_2.out +36 -0
  454. data/bin/Image-ExifTool-9.33/t/GeoTiff_3.out +36 -0
  455. data/bin/Image-ExifTool-9.33/t/Geotag.t +164 -0
  456. data/bin/Image-ExifTool-9.33/t/Geotag_2.out +9 -0
  457. data/bin/Image-ExifTool-9.33/t/Geotag_3.out +6 -0
  458. data/bin/Image-ExifTool-9.33/t/Geotag_5.out +1 -0
  459. data/bin/Image-ExifTool-9.33/t/Geotag_6.out +9 -0
  460. data/bin/Image-ExifTool-9.33/t/Geotag_7.out +53 -0
  461. data/bin/Image-ExifTool-9.33/t/Geotag_8.out +15 -0
  462. data/bin/Image-ExifTool-9.33/t/HTML.t +28 -0
  463. data/bin/Image-ExifTool-9.33/t/HTML_2.out +68 -0
  464. data/bin/Image-ExifTool-9.33/t/IPTC.t +157 -0
  465. data/bin/Image-ExifTool-9.33/t/IPTC_2.out +58 -0
  466. data/bin/Image-ExifTool-9.33/t/IPTC_4.out +56 -0
  467. data/bin/Image-ExifTool-9.33/t/IPTC_5.out +1 -0
  468. data/bin/Image-ExifTool-9.33/t/IPTC_6.out +2 -0
  469. data/bin/Image-ExifTool-9.33/t/IPTC_7.out +1 -0
  470. data/bin/Image-ExifTool-9.33/t/IPTC_8.out +20 -0
  471. data/bin/Image-ExifTool-9.33/t/ITC.t +28 -0
  472. data/bin/Image-ExifTool-9.33/t/ITC_2.out +19 -0
  473. data/bin/Image-ExifTool-9.33/t/InDesign.t +61 -0
  474. data/bin/Image-ExifTool-9.33/t/InDesign_2.out +19 -0
  475. data/bin/Image-ExifTool-9.33/t/InDesign_3.out +21 -0
  476. data/bin/Image-ExifTool-9.33/t/InDesign_4.out +11 -0
  477. data/bin/Image-ExifTool-9.33/t/JVC.t +36 -0
  478. data/bin/Image-ExifTool-9.33/t/JVC_2.out +3 -0
  479. data/bin/Image-ExifTool-9.33/t/JVC_3.out +3 -0
  480. data/bin/Image-ExifTool-9.33/t/Jpeg2000.t +49 -0
  481. data/bin/Image-ExifTool-9.33/t/Jpeg2000_2.out +63 -0
  482. data/bin/Image-ExifTool-9.33/t/Jpeg2000_3.out +51 -0
  483. data/bin/Image-ExifTool-9.33/t/Jpeg2000_4.out +15 -0
  484. data/bin/Image-ExifTool-9.33/t/Kodak.t +40 -0
  485. data/bin/Image-ExifTool-9.33/t/Kodak_2.out +109 -0
  486. data/bin/Image-ExifTool-9.33/t/Kodak_3.out +119 -0
  487. data/bin/Image-ExifTool-9.33/t/KyoceraRaw.t +28 -0
  488. data/bin/Image-ExifTool-9.33/t/KyoceraRaw_2.out +27 -0
  489. data/bin/Image-ExifTool-9.33/t/LNK.t +28 -0
  490. data/bin/Image-ExifTool-9.33/t/LNK_2.out +45 -0
  491. data/bin/Image-ExifTool-9.33/t/Lang.t +40 -0
  492. data/bin/Image-ExifTool-9.33/t/Lang_1.out +1 -0
  493. data/bin/Image-ExifTool-9.33/t/Lang_10.out +46 -0
  494. data/bin/Image-ExifTool-9.33/t/Lang_11.out +46 -0
  495. data/bin/Image-ExifTool-9.33/t/Lang_12.out +46 -0
  496. data/bin/Image-ExifTool-9.33/t/Lang_13.out +46 -0
  497. data/bin/Image-ExifTool-9.33/t/Lang_14.out +46 -0
  498. data/bin/Image-ExifTool-9.33/t/Lang_15.out +46 -0
  499. data/bin/Image-ExifTool-9.33/t/Lang_16.out +46 -0
  500. data/bin/Image-ExifTool-9.33/t/Lang_17.out +46 -0
  501. data/bin/Image-ExifTool-9.33/t/Lang_18.out +46 -0
  502. data/bin/Image-ExifTool-9.33/t/Lang_2.out +46 -0
  503. data/bin/Image-ExifTool-9.33/t/Lang_3.out +46 -0
  504. data/bin/Image-ExifTool-9.33/t/Lang_4.out +46 -0
  505. data/bin/Image-ExifTool-9.33/t/Lang_5.out +46 -0
  506. data/bin/Image-ExifTool-9.33/t/Lang_6.out +46 -0
  507. data/bin/Image-ExifTool-9.33/t/Lang_7.out +46 -0
  508. data/bin/Image-ExifTool-9.33/t/Lang_8.out +46 -0
  509. data/bin/Image-ExifTool-9.33/t/Lang_9.out +46 -0
  510. data/bin/Image-ExifTool-9.33/t/M2TS.t +29 -0
  511. data/bin/Image-ExifTool-9.33/t/M2TS_2.out +27 -0
  512. data/bin/Image-ExifTool-9.33/t/MIE.t +82 -0
  513. data/bin/Image-ExifTool-9.33/t/MIE_2.out +67 -0
  514. data/bin/Image-ExifTool-9.33/t/MIE_3.out +134 -0
  515. data/bin/Image-ExifTool-9.33/t/MIE_5.out +1 -0
  516. data/bin/Image-ExifTool-9.33/t/MIE_6.out +1 -0
  517. data/bin/Image-ExifTool-9.33/t/MIFF.t +28 -0
  518. data/bin/Image-ExifTool-9.33/t/MIFF_2.out +108 -0
  519. data/bin/Image-ExifTool-9.33/t/MP3.t +29 -0
  520. data/bin/Image-ExifTool-9.33/t/MP3_2.out +45 -0
  521. data/bin/Image-ExifTool-9.33/t/MWG.t +72 -0
  522. data/bin/Image-ExifTool-9.33/t/MWG_2.out +13 -0
  523. data/bin/Image-ExifTool-9.33/t/MWG_3.out +8 -0
  524. data/bin/Image-ExifTool-9.33/t/MWG_4.out +5 -0
  525. data/bin/Image-ExifTool-9.33/t/MWG_5.out +22 -0
  526. data/bin/Image-ExifTool-9.33/t/MXF.t +27 -0
  527. data/bin/Image-ExifTool-9.33/t/MXF_2.out +78 -0
  528. data/bin/Image-ExifTool-9.33/t/Matroska.t +29 -0
  529. data/bin/Image-ExifTool-9.33/t/Matroska_2.out +64 -0
  530. data/bin/Image-ExifTool-9.33/t/Minolta.t +50 -0
  531. data/bin/Image-ExifTool-9.33/t/Minolta_2.out +133 -0
  532. data/bin/Image-ExifTool-9.33/t/Minolta_3.out +146 -0
  533. data/bin/Image-ExifTool-9.33/t/Minolta_4.out +148 -0
  534. data/bin/Image-ExifTool-9.33/t/Nikon.t +114 -0
  535. data/bin/Image-ExifTool-9.33/t/Nikon_2.out +82 -0
  536. data/bin/Image-ExifTool-9.33/t/Nikon_3.out +98 -0
  537. data/bin/Image-ExifTool-9.33/t/Nikon_4.out +174 -0
  538. data/bin/Image-ExifTool-9.33/t/Nikon_5.out +167 -0
  539. data/bin/Image-ExifTool-9.33/t/Nikon_7.out +260 -0
  540. data/bin/Image-ExifTool-9.33/t/Nikon_8.out +4 -0
  541. data/bin/Image-ExifTool-9.33/t/Olympus.t +85 -0
  542. data/bin/Image-ExifTool-9.33/t/Olympus_2.out +79 -0
  543. data/bin/Image-ExifTool-9.33/t/Olympus_3.out +81 -0
  544. data/bin/Image-ExifTool-9.33/t/Olympus_4.out +192 -0
  545. data/bin/Image-ExifTool-9.33/t/Olympus_5.out +264 -0
  546. data/bin/Image-ExifTool-9.33/t/Olympus_6.out +151 -0
  547. data/bin/Image-ExifTool-9.33/t/Olympus_7.out +482 -0
  548. data/bin/Image-ExifTool-9.33/t/OpenEXR.t +28 -0
  549. data/bin/Image-ExifTool-9.33/t/OpenEXR_2.out +23 -0
  550. data/bin/Image-ExifTool-9.33/t/PDF.t +295 -0
  551. data/bin/Image-ExifTool-9.33/t/PDF_10.out +10 -0
  552. data/bin/Image-ExifTool-9.33/t/PDF_11.out +10 -0
  553. data/bin/Image-ExifTool-9.33/t/PDF_12.out +9 -0
  554. data/bin/Image-ExifTool-9.33/t/PDF_14.out +5 -0
  555. data/bin/Image-ExifTool-9.33/t/PDF_15.out +6 -0
  556. data/bin/Image-ExifTool-9.33/t/PDF_16.out +4 -0
  557. data/bin/Image-ExifTool-9.33/t/PDF_17.out +4 -0
  558. data/bin/Image-ExifTool-9.33/t/PDF_18.out +5 -0
  559. data/bin/Image-ExifTool-9.33/t/PDF_19.out +6 -0
  560. data/bin/Image-ExifTool-9.33/t/PDF_2.out +117 -0
  561. data/bin/Image-ExifTool-9.33/t/PDF_20.out +4 -0
  562. data/bin/Image-ExifTool-9.33/t/PDF_22.out +3 -0
  563. data/bin/Image-ExifTool-9.33/t/PDF_4.out +12 -0
  564. data/bin/Image-ExifTool-9.33/t/PDF_5.out +8 -0
  565. data/bin/Image-ExifTool-9.33/t/PDF_6.out +9 -0
  566. data/bin/Image-ExifTool-9.33/t/PDF_7.out +11 -0
  567. data/bin/Image-ExifTool-9.33/t/PDF_8.out +9 -0
  568. data/bin/Image-ExifTool-9.33/t/PDF_9.out +9 -0
  569. data/bin/Image-ExifTool-9.33/t/PGF.t +28 -0
  570. data/bin/Image-ExifTool-9.33/t/PGF_2.out +32 -0
  571. data/bin/Image-ExifTool-9.33/t/PICT.t +28 -0
  572. data/bin/Image-ExifTool-9.33/t/PICT_2.out +15 -0
  573. data/bin/Image-ExifTool-9.33/t/PLIST.t +31 -0
  574. data/bin/Image-ExifTool-9.33/t/PLIST_2.out +20 -0
  575. data/bin/Image-ExifTool-9.33/t/PLIST_3.out +20 -0
  576. data/bin/Image-ExifTool-9.33/t/PNG.t +75 -0
  577. data/bin/Image-ExifTool-9.33/t/PNG_2.out +22 -0
  578. data/bin/Image-ExifTool-9.33/t/PNG_3.out +118 -0
  579. data/bin/Image-ExifTool-9.33/t/PNG_4.out +12 -0
  580. data/bin/Image-ExifTool-9.33/t/PPM.t +40 -0
  581. data/bin/Image-ExifTool-9.33/t/PPM_2.out +15 -0
  582. data/bin/Image-ExifTool-9.33/t/PPM_3.out +9 -0
  583. data/bin/Image-ExifTool-9.33/t/PSP.t +28 -0
  584. data/bin/Image-ExifTool-9.33/t/PSP_2.out +32 -0
  585. data/bin/Image-ExifTool-9.33/t/Panasonic.t +60 -0
  586. data/bin/Image-ExifTool-9.33/t/Panasonic_2.out +99 -0
  587. data/bin/Image-ExifTool-9.33/t/Panasonic_3.out +119 -0
  588. data/bin/Image-ExifTool-9.33/t/Panasonic_4.out +177 -0
  589. data/bin/Image-ExifTool-9.33/t/Panasonic_5.out +228 -0
  590. data/bin/Image-ExifTool-9.33/t/Pentax.t +50 -0
  591. data/bin/Image-ExifTool-9.33/t/Pentax_2.out +219 -0
  592. data/bin/Image-ExifTool-9.33/t/Pentax_3.out +262 -0
  593. data/bin/Image-ExifTool-9.33/t/Pentax_4.out +123 -0
  594. data/bin/Image-ExifTool-9.33/t/PhotoCD.t +28 -0
  595. data/bin/Image-ExifTool-9.33/t/PhotoCD_2.out +35 -0
  596. data/bin/Image-ExifTool-9.33/t/PhotoMechanic.t +38 -0
  597. data/bin/Image-ExifTool-9.33/t/PhotoMechanic_2.out +81 -0
  598. data/bin/Image-ExifTool-9.33/t/PhotoMechanic_3.out +2 -0
  599. data/bin/Image-ExifTool-9.33/t/Photoshop.t +42 -0
  600. data/bin/Image-ExifTool-9.33/t/Photoshop_2.out +96 -0
  601. data/bin/Image-ExifTool-9.33/t/Photoshop_3.out +108 -0
  602. data/bin/Image-ExifTool-9.33/t/PostScript.t +49 -0
  603. data/bin/Image-ExifTool-9.33/t/PostScript_2.out +64 -0
  604. data/bin/Image-ExifTool-9.33/t/PostScript_3.out +132 -0
  605. data/bin/Image-ExifTool-9.33/t/QuickTime.t +31 -0
  606. data/bin/Image-ExifTool-9.33/t/QuickTime_2.out +128 -0
  607. data/bin/Image-ExifTool-9.33/t/QuickTime_3.out +69 -0
  608. data/bin/Image-ExifTool-9.33/t/RIFF.t +31 -0
  609. data/bin/Image-ExifTool-9.33/t/RIFF_2.out +24 -0
  610. data/bin/Image-ExifTool-9.33/t/RIFF_3.out +52 -0
  611. data/bin/Image-ExifTool-9.33/t/RIFF_4.out +16 -0
  612. data/bin/Image-ExifTool-9.33/t/RTF.t +27 -0
  613. data/bin/Image-ExifTool-9.33/t/RTF_2.out +20 -0
  614. data/bin/Image-ExifTool-9.33/t/Radiance.t +28 -0
  615. data/bin/Image-ExifTool-9.33/t/Radiance_2.out +22 -0
  616. data/bin/Image-ExifTool-9.33/t/Real.t +46 -0
  617. data/bin/Image-ExifTool-9.33/t/Real_2.out +68 -0
  618. data/bin/Image-ExifTool-9.33/t/Real_3.out +18 -0
  619. data/bin/Image-ExifTool-9.33/t/Real_4.out +11 -0
  620. data/bin/Image-ExifTool-9.33/t/Ricoh.t +47 -0
  621. data/bin/Image-ExifTool-9.33/t/Ricoh_2.out +70 -0
  622. data/bin/Image-ExifTool-9.33/t/Ricoh_3.out +98 -0
  623. data/bin/Image-ExifTool-9.33/t/Ricoh_4.out +112 -0
  624. data/bin/Image-ExifTool-9.33/t/Sanyo.t +39 -0
  625. data/bin/Image-ExifTool-9.33/t/Sanyo_2.out +101 -0
  626. data/bin/Image-ExifTool-9.33/t/Sanyo_3.out +111 -0
  627. data/bin/Image-ExifTool-9.33/t/Sigma.t +60 -0
  628. data/bin/Image-ExifTool-9.33/t/Sigma_2.out +91 -0
  629. data/bin/Image-ExifTool-9.33/t/Sigma_3.out +94 -0
  630. data/bin/Image-ExifTool-9.33/t/Sigma_4.out +63 -0
  631. data/bin/Image-ExifTool-9.33/t/Sigma_5.out +192 -0
  632. data/bin/Image-ExifTool-9.33/t/Sony.t +62 -0
  633. data/bin/Image-ExifTool-9.33/t/Sony_2.out +84 -0
  634. data/bin/Image-ExifTool-9.33/t/Sony_3.out +85 -0
  635. data/bin/Image-ExifTool-9.33/t/Sony_5.out +32 -0
  636. data/bin/Image-ExifTool-9.33/t/TestLib.pm +417 -0
  637. data/bin/Image-ExifTool-9.33/t/Unknown.t +36 -0
  638. data/bin/Image-ExifTool-9.33/t/Unknown_2.out +90 -0
  639. data/bin/Image-ExifTool-9.33/t/Unknown_3.out +90 -0
  640. data/bin/Image-ExifTool-9.33/t/Vorbis.t +28 -0
  641. data/bin/Image-ExifTool-9.33/t/Vorbis_2.out +28 -0
  642. data/bin/Image-ExifTool-9.33/t/Writer.t +913 -0
  643. data/bin/Image-ExifTool-9.33/t/Writer_10.out +240 -0
  644. data/bin/Image-ExifTool-9.33/t/Writer_11.out +37 -0
  645. data/bin/Image-ExifTool-9.33/t/Writer_13.out +160 -0
  646. data/bin/Image-ExifTool-9.33/t/Writer_14.out +67 -0
  647. data/bin/Image-ExifTool-9.33/t/Writer_15.out +171 -0
  648. data/bin/Image-ExifTool-9.33/t/Writer_16.out +1 -0
  649. data/bin/Image-ExifTool-9.33/t/Writer_17.out +1 -0
  650. data/bin/Image-ExifTool-9.33/t/Writer_18.out +3 -0
  651. data/bin/Image-ExifTool-9.33/t/Writer_19.out +34 -0
  652. data/bin/Image-ExifTool-9.33/t/Writer_2.out +168 -0
  653. data/bin/Image-ExifTool-9.33/t/Writer_22.out +4 -0
  654. data/bin/Image-ExifTool-9.33/t/Writer_24.out +1 -0
  655. data/bin/Image-ExifTool-9.33/t/Writer_25.out +38 -0
  656. data/bin/Image-ExifTool-9.33/t/Writer_26.out +32 -0
  657. data/bin/Image-ExifTool-9.33/t/Writer_27.out +14 -0
  658. data/bin/Image-ExifTool-9.33/t/Writer_28.out +1 -0
  659. data/bin/Image-ExifTool-9.33/t/Writer_29.out +2 -0
  660. data/bin/Image-ExifTool-9.33/t/Writer_30.out +2 -0
  661. data/bin/Image-ExifTool-9.33/t/Writer_31.out +97 -0
  662. data/bin/Image-ExifTool-9.33/t/Writer_32.out +3 -0
  663. data/bin/Image-ExifTool-9.33/t/Writer_33.out +3 -0
  664. data/bin/Image-ExifTool-9.33/t/Writer_34.out +3 -0
  665. data/bin/Image-ExifTool-9.33/t/Writer_35.out +187 -0
  666. data/bin/Image-ExifTool-9.33/t/Writer_36.out +2 -0
  667. data/bin/Image-ExifTool-9.33/t/Writer_37.out +2 -0
  668. data/bin/Image-ExifTool-9.33/t/Writer_38.out +62 -0
  669. data/bin/Image-ExifTool-9.33/t/Writer_39.out +4 -0
  670. data/bin/Image-ExifTool-9.33/t/Writer_4.out +85 -0
  671. data/bin/Image-ExifTool-9.33/t/Writer_40.out +4 -0
  672. data/bin/Image-ExifTool-9.33/t/Writer_41.out +3 -0
  673. data/bin/Image-ExifTool-9.33/t/Writer_42.out +5 -0
  674. data/bin/Image-ExifTool-9.33/t/Writer_43.out +5 -0
  675. data/bin/Image-ExifTool-9.33/t/Writer_44.out +2 -0
  676. data/bin/Image-ExifTool-9.33/t/Writer_45.out +1 -0
  677. data/bin/Image-ExifTool-9.33/t/Writer_46.out +77 -0
  678. data/bin/Image-ExifTool-9.33/t/Writer_47.out +56 -0
  679. data/bin/Image-ExifTool-9.33/t/Writer_48.out +29 -0
  680. data/bin/Image-ExifTool-9.33/t/Writer_50.out +3 -0
  681. data/bin/Image-ExifTool-9.33/t/Writer_51.out +386 -0
  682. data/bin/Image-ExifTool-9.33/t/Writer_6.out +182 -0
  683. data/bin/Image-ExifTool-9.33/t/Writer_7.out +149 -0
  684. data/bin/Image-ExifTool-9.33/t/Writer_9.out +237 -0
  685. data/bin/Image-ExifTool-9.33/t/XMP.t +521 -0
  686. data/bin/Image-ExifTool-9.33/t/XMP_10.out +33 -0
  687. data/bin/Image-ExifTool-9.33/t/XMP_11.out +59 -0
  688. data/bin/Image-ExifTool-9.33/t/XMP_12.out +4 -0
  689. data/bin/Image-ExifTool-9.33/t/XMP_13.out +5 -0
  690. data/bin/Image-ExifTool-9.33/t/XMP_14.out +3 -0
  691. data/bin/Image-ExifTool-9.33/t/XMP_15.out +3 -0
  692. data/bin/Image-ExifTool-9.33/t/XMP_16.out +5 -0
  693. data/bin/Image-ExifTool-9.33/t/XMP_17.out +6 -0
  694. data/bin/Image-ExifTool-9.33/t/XMP_18.out +10 -0
  695. data/bin/Image-ExifTool-9.33/t/XMP_19.out +35 -0
  696. data/bin/Image-ExifTool-9.33/t/XMP_2.out +138 -0
  697. data/bin/Image-ExifTool-9.33/t/XMP_20.out +35 -0
  698. data/bin/Image-ExifTool-9.33/t/XMP_21.out +38 -0
  699. data/bin/Image-ExifTool-9.33/t/XMP_22.out +38 -0
  700. data/bin/Image-ExifTool-9.33/t/XMP_23.out +9 -0
  701. data/bin/Image-ExifTool-9.33/t/XMP_24.out +31 -0
  702. data/bin/Image-ExifTool-9.33/t/XMP_25.out +28 -0
  703. data/bin/Image-ExifTool-9.33/t/XMP_26.out +52 -0
  704. data/bin/Image-ExifTool-9.33/t/XMP_27.out +93 -0
  705. data/bin/Image-ExifTool-9.33/t/XMP_28.out +44 -0
  706. data/bin/Image-ExifTool-9.33/t/XMP_29.out +24 -0
  707. data/bin/Image-ExifTool-9.33/t/XMP_3.out +136 -0
  708. data/bin/Image-ExifTool-9.33/t/XMP_30.out +90 -0
  709. data/bin/Image-ExifTool-9.33/t/XMP_31.out +19 -0
  710. data/bin/Image-ExifTool-9.33/t/XMP_32.out +2 -0
  711. data/bin/Image-ExifTool-9.33/t/XMP_34.out +2 -0
  712. data/bin/Image-ExifTool-9.33/t/XMP_36.out +18 -0
  713. data/bin/Image-ExifTool-9.33/t/XMP_37.out +35 -0
  714. data/bin/Image-ExifTool-9.33/t/XMP_39.out +44 -0
  715. data/bin/Image-ExifTool-9.33/t/XMP_40.out +3 -0
  716. data/bin/Image-ExifTool-9.33/t/XMP_41.out +175 -0
  717. data/bin/Image-ExifTool-9.33/t/XMP_5.out +29 -0
  718. data/bin/Image-ExifTool-9.33/t/XMP_6.out +87 -0
  719. data/bin/Image-ExifTool-9.33/t/XMP_7.out +118 -0
  720. data/bin/Image-ExifTool-9.33/t/XMP_8.out +17 -0
  721. data/bin/Image-ExifTool-9.33/t/XMP_9.out +36 -0
  722. data/bin/Image-ExifTool-9.33/t/ZIP.t +69 -0
  723. data/bin/Image-ExifTool-9.33/t/ZIP_2.out +18 -0
  724. data/bin/Image-ExifTool-9.33/t/ZIP_3.out +17 -0
  725. data/bin/Image-ExifTool-9.33/t/ZIP_4.out +213 -0
  726. data/bin/Image-ExifTool-9.33/t/ZIP_5.out +134 -0
  727. data/bin/Image-ExifTool-9.33/t/ZIP_6.out +49 -0
  728. data/bin/Image-ExifTool-9.33/t/ZIP_7.out +28 -0
  729. data/bin/Image-ExifTool-9.33/t/images/AFCP.jpg +0 -0
  730. data/bin/Image-ExifTool-9.33/t/images/AIFF.aif +0 -0
  731. data/bin/Image-ExifTool-9.33/t/images/APE.ape +0 -0
  732. data/bin/Image-ExifTool-9.33/t/images/APE.mpc +0 -0
  733. data/bin/Image-ExifTool-9.33/t/images/ASF.wmv +0 -0
  734. data/bin/Image-ExifTool-9.33/t/images/BMP.bmp +0 -0
  735. data/bin/Image-ExifTool-9.33/t/images/BigTIFF.btf +0 -0
  736. data/bin/Image-ExifTool-9.33/t/images/Canon.jpg +0 -0
  737. data/bin/Image-ExifTool-9.33/t/images/Canon1DmkIII.jpg +0 -0
  738. data/bin/Image-ExifTool-9.33/t/images/CanonRaw.cr2 +0 -0
  739. data/bin/Image-ExifTool-9.33/t/images/CanonRaw.crw +0 -0
  740. data/bin/Image-ExifTool-9.33/t/images/CanonVRD.vrd +0 -0
  741. data/bin/Image-ExifTool-9.33/t/images/CaptureOne.eip +0 -0
  742. data/bin/Image-ExifTool-9.33/t/images/Casio.jpg +0 -0
  743. data/bin/Image-ExifTool-9.33/t/images/Casio2.jpg +0 -0
  744. data/bin/Image-ExifTool-9.33/t/images/CasioQVCI.jpg +0 -0
  745. data/bin/Image-ExifTool-9.33/t/images/DICOM.dcm +0 -0
  746. data/bin/Image-ExifTool-9.33/t/images/DNG.dng +0 -0
  747. data/bin/Image-ExifTool-9.33/t/images/DV.dv +0 -0
  748. data/bin/Image-ExifTool-9.33/t/images/DjVu.djvu +0 -0
  749. data/bin/Image-ExifTool-9.33/t/images/EXE.elf +0 -0
  750. data/bin/Image-ExifTool-9.33/t/images/EXE.exe +0 -0
  751. data/bin/Image-ExifTool-9.33/t/images/EXE.macho +0 -0
  752. data/bin/Image-ExifTool-9.33/t/images/ExifTool.jpg +0 -0
  753. data/bin/Image-ExifTool-9.33/t/images/ExifTool.tif +0 -0
  754. data/bin/Image-ExifTool-9.33/t/images/ExtendedXMP.jpg +0 -0
  755. data/bin/Image-ExifTool-9.33/t/images/FLAC.flac +0 -0
  756. data/bin/Image-ExifTool-9.33/t/images/FLAC.ogg +0 -0
  757. data/bin/Image-ExifTool-9.33/t/images/FLIR.fpf +0 -0
  758. data/bin/Image-ExifTool-9.33/t/images/FLIR.jpg +0 -0
  759. data/bin/Image-ExifTool-9.33/t/images/Flash.flv +0 -0
  760. data/bin/Image-ExifTool-9.33/t/images/Flash.swf +0 -0
  761. data/bin/Image-ExifTool-9.33/t/images/FlashPix.ppt +0 -0
  762. data/bin/Image-ExifTool-9.33/t/images/Font.afm +28 -0
  763. data/bin/Image-ExifTool-9.33/t/images/Font.dfont +0 -0
  764. data/bin/Image-ExifTool-9.33/t/images/Font.pfa +38 -0
  765. data/bin/Image-ExifTool-9.33/t/images/Font.pfb +0 -0
  766. data/bin/Image-ExifTool-9.33/t/images/Font.pfm +0 -0
  767. data/bin/Image-ExifTool-9.33/t/images/Font.ttf +0 -0
  768. data/bin/Image-ExifTool-9.33/t/images/FotoStation.jpg +0 -0
  769. data/bin/Image-ExifTool-9.33/t/images/FujiFilm.jpg +0 -0
  770. data/bin/Image-ExifTool-9.33/t/images/FujiFilm.raf +0 -0
  771. data/bin/Image-ExifTool-9.33/t/images/GE.jpg +0 -0
  772. data/bin/Image-ExifTool-9.33/t/images/GIF.gif +0 -0
  773. data/bin/Image-ExifTool-9.33/t/images/GIMP.xcf +0 -0
  774. data/bin/Image-ExifTool-9.33/t/images/GPS.jpg +0 -0
  775. data/bin/Image-ExifTool-9.33/t/images/GeoTiff.tif +0 -0
  776. data/bin/Image-ExifTool-9.33/t/images/Geotag.gpx +23 -0
  777. data/bin/Image-ExifTool-9.33/t/images/Geotag.igc +24 -0
  778. data/bin/Image-ExifTool-9.33/t/images/Geotag.log +13 -0
  779. data/bin/Image-ExifTool-9.33/t/images/Geotag.xml +23 -0
  780. data/bin/Image-ExifTool-9.33/t/images/Geotag2.log +7 -0
  781. data/bin/Image-ExifTool-9.33/t/images/HTML.html +77 -0
  782. data/bin/Image-ExifTool-9.33/t/images/IPTC.jpg +0 -0
  783. data/bin/Image-ExifTool-9.33/t/images/ITC.itc +0 -0
  784. data/bin/Image-ExifTool-9.33/t/images/InDesign.indd +0 -0
  785. data/bin/Image-ExifTool-9.33/t/images/JVC.jpg +0 -0
  786. data/bin/Image-ExifTool-9.33/t/images/JVC2.jpg +0 -0
  787. data/bin/Image-ExifTool-9.33/t/images/Jpeg2000.j2c +0 -0
  788. data/bin/Image-ExifTool-9.33/t/images/Jpeg2000.jp2 +0 -0
  789. data/bin/Image-ExifTool-9.33/t/images/Kodak.jpg +0 -0
  790. data/bin/Image-ExifTool-9.33/t/images/KyoceraRaw.raw +0 -0
  791. data/bin/Image-ExifTool-9.33/t/images/LNK.lnk +0 -0
  792. data/bin/Image-ExifTool-9.33/t/images/M2TS.mts +0 -0
  793. data/bin/Image-ExifTool-9.33/t/images/MIE.mie +0 -0
  794. data/bin/Image-ExifTool-9.33/t/images/MIFF.miff +0 -0
  795. data/bin/Image-ExifTool-9.33/t/images/MP3.mp3 +0 -0
  796. data/bin/Image-ExifTool-9.33/t/images/MWG.jpg +0 -0
  797. data/bin/Image-ExifTool-9.33/t/images/MXF.mxf +0 -0
  798. data/bin/Image-ExifTool-9.33/t/images/Matroska.mkv +0 -0
  799. data/bin/Image-ExifTool-9.33/t/images/Minolta.jpg +0 -0
  800. data/bin/Image-ExifTool-9.33/t/images/Minolta.mrw +0 -0
  801. data/bin/Image-ExifTool-9.33/t/images/Nikon.jpg +0 -0
  802. data/bin/Image-ExifTool-9.33/t/images/Nikon.nef +0 -0
  803. data/bin/Image-ExifTool-9.33/t/images/NikonD2Hs.jpg +0 -0
  804. data/bin/Image-ExifTool-9.33/t/images/NikonD70.jpg +0 -0
  805. data/bin/Image-ExifTool-9.33/t/images/OOXML.docx +0 -0
  806. data/bin/Image-ExifTool-9.33/t/images/Olympus.jpg +0 -0
  807. data/bin/Image-ExifTool-9.33/t/images/Olympus2.jpg +0 -0
  808. data/bin/Image-ExifTool-9.33/t/images/OlympusE1.jpg +0 -0
  809. data/bin/Image-ExifTool-9.33/t/images/OpenDoc.ods +0 -0
  810. data/bin/Image-ExifTool-9.33/t/images/OpenEXR.exr +0 -0
  811. data/bin/Image-ExifTool-9.33/t/images/PDF.pdf +0 -0
  812. data/bin/Image-ExifTool-9.33/t/images/PDF2.pdf +0 -0
  813. data/bin/Image-ExifTool-9.33/t/images/PGF.pgf +0 -0
  814. data/bin/Image-ExifTool-9.33/t/images/PICT.pict +0 -0
  815. data/bin/Image-ExifTool-9.33/t/images/PLIST-bin.plist +0 -0
  816. data/bin/Image-ExifTool-9.33/t/images/PLIST-xml.plist +35 -0
  817. data/bin/Image-ExifTool-9.33/t/images/PNG.png +0 -0
  818. data/bin/Image-ExifTool-9.33/t/images/PPM.ppm +5 -0
  819. data/bin/Image-ExifTool-9.33/t/images/PSP.psp +0 -0
  820. data/bin/Image-ExifTool-9.33/t/images/Panasonic.jpg +0 -0
  821. data/bin/Image-ExifTool-9.33/t/images/Panasonic.rw2 +0 -0
  822. data/bin/Image-ExifTool-9.33/t/images/Pentax.avi +0 -0
  823. data/bin/Image-ExifTool-9.33/t/images/Pentax.jpg +0 -0
  824. data/bin/Image-ExifTool-9.33/t/images/PhotoCD.pcd +0 -0
  825. data/bin/Image-ExifTool-9.33/t/images/PhotoMechanic.jpg +0 -0
  826. data/bin/Image-ExifTool-9.33/t/images/Photoshop.psd +0 -0
  827. data/bin/Image-ExifTool-9.33/t/images/PostScript.eps +108 -0
  828. data/bin/Image-ExifTool-9.33/t/images/QuickTime.m4a +0 -0
  829. data/bin/Image-ExifTool-9.33/t/images/QuickTime.mov +0 -0
  830. data/bin/Image-ExifTool-9.33/t/images/RIFF.avi +0 -0
  831. data/bin/Image-ExifTool-9.33/t/images/RIFF.wav +0 -0
  832. data/bin/Image-ExifTool-9.33/t/images/RIFF.webp +0 -0
  833. data/bin/Image-ExifTool-9.33/t/images/RTF.rtf +25 -0
  834. data/bin/Image-ExifTool-9.33/t/images/Radiance.hdr +0 -0
  835. data/bin/Image-ExifTool-9.33/t/images/Real.ra +0 -0
  836. data/bin/Image-ExifTool-9.33/t/images/Real.ram +1 -0
  837. data/bin/Image-ExifTool-9.33/t/images/Real.rm +0 -0
  838. data/bin/Image-ExifTool-9.33/t/images/Ricoh.jpg +0 -0
  839. data/bin/Image-ExifTool-9.33/t/images/Ricoh2.jpg +0 -0
  840. data/bin/Image-ExifTool-9.33/t/images/Sanyo.jpg +0 -0
  841. data/bin/Image-ExifTool-9.33/t/images/Sigma.jpg +0 -0
  842. data/bin/Image-ExifTool-9.33/t/images/Sigma.x3f +0 -0
  843. data/bin/Image-ExifTool-9.33/t/images/SigmaDP2.x3f +0 -0
  844. data/bin/Image-ExifTool-9.33/t/images/Sony.jpg +0 -0
  845. data/bin/Image-ExifTool-9.33/t/images/Sony.pmp +0 -0
  846. data/bin/Image-ExifTool-9.33/t/images/Unknown.jpg +0 -0
  847. data/bin/Image-ExifTool-9.33/t/images/Vorbis.ogg +0 -0
  848. data/bin/Image-ExifTool-9.33/t/images/Writer.jpg +0 -0
  849. data/bin/Image-ExifTool-9.33/t/images/XMP.inx +108 -0
  850. data/bin/Image-ExifTool-9.33/t/images/XMP.jpg +0 -0
  851. data/bin/Image-ExifTool-9.33/t/images/XMP.svg +33 -0
  852. data/bin/Image-ExifTool-9.33/t/images/XMP.xml +98 -0
  853. data/bin/Image-ExifTool-9.33/t/images/XMP.xmp +99 -0
  854. data/bin/Image-ExifTool-9.33/t/images/XMP2.xmp +25 -0
  855. data/bin/Image-ExifTool-9.33/t/images/XMP3.xmp +43 -0
  856. data/bin/Image-ExifTool-9.33/t/images/XMP4.xmp +93 -0
  857. data/bin/Image-ExifTool-9.33/t/images/XMP5.xmp +158 -0
  858. data/bin/Image-ExifTool-9.33/t/images/ZIP.gz +0 -0
  859. data/bin/Image-ExifTool-9.33/t/images/ZIP.zip +0 -0
  860. data/bin/Image-ExifTool-9.33/t/images/iWork.numbers +0 -0
  861. data/lib/exiftool_vendored.rb +10 -0
  862. data/lib/exiftool_vendored/version.rb +3 -0
  863. data/lib/exiftool_vendored/version_extractor.rb +17 -0
  864. metadata +977 -0
@@ -0,0 +1,3674 @@
1
+ #------------------------------------------------------------------------------
2
+ # File: WriteExif.pl
3
+ #
4
+ # Description: Write EXIF meta information
5
+ #
6
+ # Revisions: 12/13/2004 - P. Harvey Created
7
+ #------------------------------------------------------------------------------
8
+
9
+ package Image::ExifTool::Exif;
10
+
11
+ use strict;
12
+ use vars qw($VERSION $AUTOLOAD @formatSize @formatName %formatNumber
13
+ %compression %photometricInterpretation %orientation);
14
+
15
+ use Image::ExifTool::Fixup;
16
+
17
+ sub InsertWritableProperties($$;$);
18
+
19
+ # some information may be stored in different IFD's with the same meaning.
20
+ # Use this lookup to decide when we should delete information that is stored
21
+ # in another IFD when we write it to the preferred IFD.
22
+ my %crossDelete = (
23
+ ExifIFD => 'IFD0',
24
+ IFD0 => 'ExifIFD',
25
+ );
26
+
27
+ # mandatory tag default values
28
+ my %mandatory = (
29
+ IFD0 => {
30
+ 0x011a => 72, # XResolution
31
+ 0x011b => 72, # YResolution
32
+ 0x0128 => 2, # ResolutionUnit (inches)
33
+ 0x0213 => 1, # YCbCrPositioning (centered)
34
+ # 0x8769 => ????, # ExifOffset
35
+ },
36
+ IFD1 => {
37
+ 0x0103 => 6, # Compression (JPEG)
38
+ 0x011a => 72, # XResolution
39
+ 0x011b => 72, # YResolution
40
+ 0x0128 => 2, # ResolutionUnit (inches)
41
+ },
42
+ ExifIFD => {
43
+ 0x9000 => '0230', # ExifVersion
44
+ 0x9101 => "1 2 3 0",# ComponentsConfiguration
45
+ 0xa000 => '0100', # FlashpixVersion
46
+ 0xa001 => 0xffff, # ColorSpace (uncalibrated)
47
+ # 0xa002 => ????, # ExifImageWidth
48
+ # 0xa003 => ????, # ExifImageHeight
49
+ },
50
+ GPS => {
51
+ 0x0000 => '2 3 0 0',# GPSVersionID
52
+ },
53
+ InteropIFD => {
54
+ 0x0002 => '0100', # InteropVersion
55
+ },
56
+ );
57
+
58
+ # The main EXIF table is unique because the tags from this table may appear
59
+ # in many different directories. For this reason, we introduce a
60
+ # "WriteGroup" member to the tagInfo that tells us the preferred location
61
+ # for writing each tag. Here is the lookup for Writable flag (format)
62
+ # and WriteGroup for all writable tags
63
+ # - WriteGroup is ExifIFD unless otherwise specified
64
+ # - Protected is 1 if the tag shouldn't be copied with SetNewValuesFromFile()
65
+ my %writeTable = (
66
+ 0x0001 => { # InteropIndex
67
+ Protected => 1,
68
+ Writable => 'string',
69
+ WriteGroup => 'InteropIFD',
70
+ },
71
+ 0x0002 => { # InteropVersion
72
+ Protected => 1,
73
+ Writable => 'undef',
74
+ Mandatory => 1,
75
+ WriteGroup => 'InteropIFD',
76
+ },
77
+ 0x000b => { # ProcessingSoftware
78
+ Writable => 'string',
79
+ WriteGroup => 'IFD0',
80
+ },
81
+ 0x00fe => { # SubfileType
82
+ Protected => 1,
83
+ Writable => 'int32u',
84
+ WriteGroup => 'IFD0',
85
+ },
86
+ 0x00ff => { # OldSubfileType
87
+ Protected => 1,
88
+ Writable => 'int16u',
89
+ WriteGroup => 'IFD0',
90
+ },
91
+ 0x0100 => { # ImageWidth
92
+ Protected => 1,
93
+ Writable => 'int32u',
94
+ WriteGroup => 'IFD0',
95
+ },
96
+ 0x0101 => { # ImageHeight
97
+ Protected => 1,
98
+ Writable => 'int32u',
99
+ WriteGroup => 'IFD0',
100
+ },
101
+ 0x0102 => { # BitsPerSample
102
+ Protected => 1,
103
+ Writable => 'int16u',
104
+ WriteGroup => 'IFD0',
105
+ Count => -1, # can be 1 or 3: -1 means 'variable'
106
+ },
107
+ 0x0103 => { # Compression
108
+ Protected => 1,
109
+ Writable => 'int16u',
110
+ WriteGroup => 'IFD0',
111
+ Mandatory => 1,
112
+ },
113
+ 0x0106 => { # PhotometricInterpretation
114
+ Protected => 1,
115
+ Writable => 'int16u',
116
+ WriteGroup => 'IFD0',
117
+ },
118
+ 0x0107 => { # Thresholding
119
+ Protected => 1,
120
+ Writable => 'int16u',
121
+ WriteGroup => 'IFD0',
122
+ },
123
+ 0x0108 => { # CellWidth
124
+ Protected => 1,
125
+ Writable => 'int16u',
126
+ WriteGroup => 'IFD0',
127
+ },
128
+ 0x0109 => { # CellLength
129
+ Protected => 1,
130
+ Writable => 'int16u',
131
+ WriteGroup => 'IFD0',
132
+ },
133
+ 0x010a => { # FillOrder
134
+ Protected => 1,
135
+ Writable => 'int16u',
136
+ WriteGroup => 'IFD0',
137
+ },
138
+ 0x010d => { # DocumentName
139
+ Writable => 'string',
140
+ WriteGroup => 'IFD0',
141
+ },
142
+ 0x010e => { # ImageDescription
143
+ Writable => 'string',
144
+ WriteGroup => 'IFD0',
145
+ },
146
+ 0x010f => { # Make
147
+ Writable => 'string',
148
+ WriteGroup => 'IFD0',
149
+ },
150
+ 0x0110 => { # Model
151
+ Writable => 'string',
152
+ WriteGroup => 'IFD0',
153
+ },
154
+ 0x0112 => { # Orientation
155
+ Writable => 'int16u',
156
+ WriteGroup => 'IFD0',
157
+ },
158
+ 0x0115 => { # SamplesPerPixel
159
+ Protected => 1,
160
+ Writable => 'int16u',
161
+ WriteGroup => 'IFD0',
162
+ },
163
+ 0x0116 => { # RowsPerStrip
164
+ Protected => 1,
165
+ Writable => 'int32u',
166
+ WriteGroup => 'IFD0',
167
+ },
168
+ 0x0118 => { # MinSampleValue
169
+ Writable => 'int16u',
170
+ WriteGroup => 'IFD0',
171
+ },
172
+ 0x0119 => { # MaxSampleValue
173
+ Writable => 'int16u',
174
+ WriteGroup => 'IFD0',
175
+ },
176
+ 0x011a => { # XResolution
177
+ Writable => 'rational64u',
178
+ WriteGroup => 'IFD0',
179
+ Mandatory => 1,
180
+ },
181
+ 0x011b => { # YResolution
182
+ Writable => 'rational64u',
183
+ WriteGroup => 'IFD0',
184
+ Mandatory => 1,
185
+ },
186
+ 0x011c => { # PlanarConfiguration
187
+ Protected => 1,
188
+ Writable => 'int16u',
189
+ WriteGroup => 'IFD0',
190
+ },
191
+ 0x011d => { # PageName
192
+ Writable => 'string',
193
+ WriteGroup => 'IFD0',
194
+ },
195
+ 0x011e => { # XPosition
196
+ Writable => 'rational64u',
197
+ WriteGroup => 'IFD0',
198
+ },
199
+ 0x011f => { # YPosition
200
+ Writable => 'rational64u',
201
+ WriteGroup => 'IFD0',
202
+ },
203
+ 0x0122 => { # GrayResponseUnit
204
+ Writable => 'int16u',
205
+ WriteGroup => 'IFD0',
206
+ },
207
+ 0x0128 => { # ResolutionUnit
208
+ Writable => 'int16u',
209
+ WriteGroup => 'IFD0',
210
+ Mandatory => 1,
211
+ },
212
+ 0x0129 => { # PageNumber
213
+ Writable => 'int16u',
214
+ WriteGroup => 'IFD0',
215
+ Count => 2,
216
+ },
217
+ 0x012d => { # TransferFunction
218
+ Protected => 1,
219
+ Writable => 'int16u',
220
+ WriteGroup => 'IFD0',
221
+ Count => 768,
222
+ },
223
+ 0x0131 => { # Software
224
+ Writable => 'string',
225
+ WriteGroup => 'IFD0',
226
+ },
227
+ 0x0132 => { # ModifyDate
228
+ Writable => 'string',
229
+ Shift => 'Time',
230
+ WriteGroup => 'IFD0',
231
+ PrintConvInv => '$self->InverseDateTime($val,0)',
232
+ },
233
+ 0x013b => { # Artist
234
+ Writable => 'string',
235
+ WriteGroup => 'IFD0',
236
+ },
237
+ 0x013c => { # HostComputer
238
+ Writable => 'string',
239
+ WriteGroup => 'IFD0',
240
+ },
241
+ 0x013d => { # Predictor
242
+ Protected => 1,
243
+ Writable => 'int16u',
244
+ WriteGroup => 'IFD0',
245
+ },
246
+ 0x013e => { # WhitePoint
247
+ Writable => 'rational64u',
248
+ WriteGroup => 'IFD0',
249
+ Count => 2,
250
+ },
251
+ 0x013f => { # PrimaryChromaticities
252
+ Writable => 'rational64u',
253
+ WriteGroup => 'IFD0',
254
+ Count => 6,
255
+ },
256
+ 0x0141 => { # HalftoneHints
257
+ Writable => 'int16u',
258
+ WriteGroup => 'IFD0',
259
+ Count => 2,
260
+ },
261
+ 0x0142 => { # TileWidth
262
+ Protected => 1,
263
+ Writable => 'int32u',
264
+ WriteGroup => 'IFD0',
265
+ },
266
+ 0x0143 => { # TileLength
267
+ Protected => 1,
268
+ Writable => 'int32u',
269
+ WriteGroup => 'IFD0',
270
+ },
271
+ 0x014c => { # InkSet
272
+ Writable => 'int16u',
273
+ WriteGroup => 'IFD0',
274
+ },
275
+ 0x0150 => { # TargetPrinter
276
+ Writable => 'string',
277
+ WriteGroup => 'IFD0',
278
+ },
279
+ 0x013c => { # HostComputer
280
+ Writable => 'string',
281
+ WriteGroup => 'IFD0',
282
+ },
283
+ 0x0211 => { # YCbCrCoefficients
284
+ Protected => 1,
285
+ Writable => 'rational64u',
286
+ WriteGroup => 'IFD0',
287
+ Count => 3,
288
+ },
289
+ 0x0212 => { # YCbCrSubSampling
290
+ Protected => 1,
291
+ Writable => 'int16u',
292
+ WriteGroup => 'IFD0',
293
+ Count => 2,
294
+ },
295
+ 0x0213 => { # YCbCrPositioning
296
+ Protected => 1,
297
+ Writable => 'int16u',
298
+ WriteGroup => 'IFD0',
299
+ Mandatory => 1,
300
+ },
301
+ 0x0214 => { # ReferenceBlackWhite
302
+ Writable => 'rational64u',
303
+ WriteGroup => 'IFD0',
304
+ Count => 6,
305
+ },
306
+ 0x1000 => { # RelatedImageFileFormat
307
+ Protected => 1,
308
+ Writable => 'string',
309
+ WriteGroup => 'InteropIFD',
310
+ },
311
+ 0x1001 => { # RelatedImageWidth
312
+ Protected => 1,
313
+ Writable => 'int16u',
314
+ WriteGroup => 'InteropIFD',
315
+ },
316
+ 0x1002 => { # RelatedImageHeight (more commonly RelatedImageLength)
317
+ Protected => 1,
318
+ Writable => 'int16u',
319
+ WriteGroup => 'InteropIFD',
320
+ },
321
+ 0x4746 => { # Rating (MicrosoftPhoto)
322
+ Writable => 'int16u',
323
+ WriteGroup => 'IFD0',
324
+ Avoid => 1,
325
+ },
326
+ 0x4749 => { # RatingPercent (MicrosoftPhoto)
327
+ Writable => 'int16u',
328
+ WriteGroup => 'IFD0',
329
+ Avoid => 1,
330
+ },
331
+ 0x828d => { # CFARepeatPatternDim
332
+ Protected => 1,
333
+ Writable => 'int16u',
334
+ WriteGroup => 'SubIFD',
335
+ Count => 2,
336
+ },
337
+ 0x828e => { # CFAPattern2
338
+ Protected => 1,
339
+ Writable => 'int8u',
340
+ WriteGroup => 'SubIFD',
341
+ Count => -1,
342
+ },
343
+ 0x8298 => { # Copyright
344
+ Writable => 'string',
345
+ WriteGroup => 'IFD0',
346
+ RawConvInv => sub {
347
+ my ($val, $self) = @_;
348
+ # encode if necessary
349
+ my $enc = $self->Options('CharsetEXIF');
350
+ $val = $self->Encode($val,$enc) if $enc and $val !~ /\0/;
351
+ if ($val =~ /(.*?)\s*[\n\r]+\s*(.*)/s) {
352
+ return $1 . "\0" unless length $2;
353
+ # photographer copyright set to ' ' if it doesn't exist, according to spec.
354
+ return((length($1) ? $1 : ' ') . "\0" . $2 . "\0");
355
+ }
356
+ return $val . "\0";
357
+ },
358
+ },
359
+ #
360
+ # Most of the tags below this belong in the ExifIFD...
361
+ #
362
+ 0x829a => { # ExposureTime
363
+ Writable => 'rational64u',
364
+ PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
365
+ },
366
+ 0x829d => { # FNumber
367
+ Writable => 'rational64u',
368
+ PrintConvInv => '$val',
369
+ },
370
+ 0x8546 => { # SEMInfo
371
+ Writable => 'string',
372
+ WriteGroup => 'IFD0',
373
+ },
374
+ 0x8822 => 'int16u', # ExposureProgram
375
+ 0x8824 => 'string', # SpectralSensitivity
376
+ 0x8827 => { # ISO
377
+ Writable => 'int16u',
378
+ Count => -1,
379
+ PrintConvInv => '$val=~tr/,//d; $val',
380
+ },
381
+ 0x882a => { # TimeZoneOffset
382
+ Writable => 'int16s',
383
+ Count => -1, # can be 1 or 2
384
+ Notes => q{
385
+ 1 or 2 values: 1. The time zone offset of DateTimeOriginal from GMT in
386
+ hours, 2. If present, the time zone offset of ModifyDate
387
+ },
388
+ },
389
+ 0x882b => 'int16u', # SelfTimerMode
390
+ 0x8830 => 'int16u', # SensitivityType
391
+ 0x8831 => 'int32u', # StandardOutputSensitivity
392
+ 0x8832 => 'int32u', # RecommendedExposureIndex
393
+ 0x8833 => 'int32u', # ISOSpeed
394
+ 0x8834 => 'int32u', # ISOSpeedLatitudeyyy
395
+ 0x8835 => 'int32u', # ISOSpeedLatitudezzz
396
+ 0x9000 => { # ExifVersion
397
+ Writable => 'undef',
398
+ Mandatory => 1,
399
+ PrintConvInv => '$val=~tr/.//d; $val=~/^\d{4}$/ ? $val : undef',
400
+ },
401
+ 0x9003 => { # DateTimeOriginal
402
+ Writable => 'string',
403
+ Shift => 'Time',
404
+ PrintConvInv => '$self->InverseDateTime($val,0)',
405
+ },
406
+ 0x9004 => { # CreateDate
407
+ Writable => 'string',
408
+ Shift => 'Time',
409
+ PrintConvInv => '$self->InverseDateTime($val,0)',
410
+ },
411
+ 0x9101 => { # ComponentsConfiguration
412
+ Protected => 1,
413
+ Writable => 'undef',
414
+ Count => 4,
415
+ Mandatory => 1,
416
+ ValueConvInv => '$val=~tr/,//d; $val', # (so we can copy from XMP with -n)
417
+ },
418
+ 0x9102 => { # CompressedBitsPerPixel
419
+ Protected => 1,
420
+ Writable => 'rational64u',
421
+ },
422
+ 0x9201 => { # ShutterSpeedValue
423
+ Writable => 'rational64s',
424
+ ValueConvInv => '$val>0 ? -log($val)/log(2) : -100',
425
+ # do eval to convert things like '1/100'
426
+ PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
427
+ },
428
+ 0x9202 => { # ApertureValue
429
+ Writable => 'rational64u',
430
+ ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0',
431
+ PrintConvInv => '$val',
432
+ },
433
+ 0x9203 => 'rational64s',# BrightnessValue
434
+ 0x9204 => { # ExposureCompensation
435
+ Writable => 'rational64s',
436
+ # do eval to convert things like '+2/3'
437
+ PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
438
+ },
439
+ 0x9205 => { # MaxApertureValue
440
+ Writable => 'rational64u',
441
+ ValueConvInv => '$val>0 ? 2*log($val)/log(2) : 0',
442
+ PrintConvInv => '$val',
443
+ },
444
+ 0x9206 => { # SubjectDistance
445
+ Writable => 'rational64u',
446
+ PrintConvInv => '$val=~s/\s*m$//;$val',
447
+ },
448
+ 0x9207 => 'int16u', # MeteringMode
449
+ 0x9208 => 'int16u', # LightSource
450
+ 0x9209 => 'int16u', # Flash
451
+ 0x920a => { # FocalLength
452
+ Writable => 'rational64u',
453
+ PrintConvInv => '$val=~s/\s*mm$//;$val',
454
+ },
455
+ 0x9211 => 'int32u', # ImageNumber
456
+ 0x9212 => 'string', # SecurityClassification
457
+ 0x9213 => 'string', # ImageHistory
458
+ 0x9214 => { # SubjectArea
459
+ Writable => 'int16u',
460
+ Count => -1, # 2, 3 or 4 values
461
+ },
462
+ # 0x927c => 'undef', # MakerNotes
463
+ 0x9286 => { # UserComment
464
+ Writable => 'undef',
465
+ # (starts with "ASCII\0\0\0", "UNICODE\0", "JIS\0\0\0\0\0" or "\0\0\0\0\0\0\0\0")
466
+ RawConvInv => 'Image::ExifTool::Exif::EncodeExifText($self,$val)',
467
+ # SHOULD ADD SPECIAL LOGIC TO ALLOW CONDITIONAL OVERWRITE OF
468
+ # "UNKNOWN" VALUES FILLED WITH SPACES
469
+ },
470
+ 0x9290 => { # SubSecTime
471
+ Writable => 'string',
472
+ # extract fractional seconds from a full date/time value
473
+ ValueConvInv => '$val=~/^(\d+)\s*$/ ? $1 : ($val=~/\.(\d+)/ ? $1 : undef)',
474
+ },
475
+ 0x9291 => { # SubSecTimeOriginal
476
+ Writable => 'string',
477
+ ValueConvInv => '$val=~/^(\d+)\s*$/ ? $1 : ($val=~/\.(\d+)/ ? $1 : undef)',
478
+ },
479
+ 0x9292 => { # SubSecTimeDigitized
480
+ Writable => 'string',
481
+ ValueConvInv => '$val=~/^(\d+)\s*$/ ? $1 : ($val=~/\.(\d+)/ ? $1 : undef)',
482
+ },
483
+ 0x935c => { # ImageSourceData
484
+ Writable => 'undef',
485
+ WriteGroup => 'IFD0',
486
+ Protected => 1,
487
+ },
488
+ # 0x9928 => 'undef', # Opto-ElectricConversionFactor
489
+ 0x9c9b => { # XPTitle
490
+ Writable => 'int8u',
491
+ WriteGroup => 'IFD0',
492
+ Notes => q{
493
+ tags 0x9c9b-0x9c9f are used by Windows Explorer; special characters
494
+ in these values are converted to UTF-8 by default, or Windows Latin1
495
+ with the -L option. XPTitle is ignored by Windows Explorer if
496
+ ImageDescription exists
497
+ },
498
+ ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"',
499
+ },
500
+ 0x9c9c => { # XPComment
501
+ Writable => 'int8u',
502
+ WriteGroup => 'IFD0',
503
+ ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"',
504
+ },
505
+ 0x9c9d => { # XPAuthor
506
+ Writable => 'int8u',
507
+ WriteGroup => 'IFD0',
508
+ Notes => 'ignored by Windows Explorer if Artist exists',
509
+ ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"',
510
+ },
511
+ 0x9c9e => { # XPKeywords
512
+ Writable => 'int8u',
513
+ WriteGroup => 'IFD0',
514
+ ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"',
515
+ },
516
+ 0x9c9f => { # XPSubject
517
+ Writable => 'int8u',
518
+ WriteGroup => 'IFD0',
519
+ ValueConvInv => '$self->Encode($val,"UCS2","II") . "\0\0"',
520
+ },
521
+ 0xa000 => { # FlashpixVersion
522
+ Writable => 'undef',
523
+ Mandatory => 1,
524
+ PrintConvInv => '$val=~tr/.//d; $val=~/^\d{4}$/ ? $val : undef',
525
+ },
526
+ 0xa001 => { # ColorSpace
527
+ Writable => 'int16u',
528
+ Mandatory => 1,
529
+ },
530
+ 0xa002 => { # ExifImageWidth (could also be int32u)
531
+ Writable => 'int16u',
532
+ Mandatory => 1,
533
+ },
534
+ 0xa003 => { # ExifImageHeight (could also be int32u)
535
+ Writable => 'int16u',
536
+ Mandatory => 1,
537
+ },
538
+ 0xa004 => 'string', # RelatedSoundFile
539
+ 0xa20b => { # FlashEnergy
540
+ Writable => 'rational64u',
541
+ Count => -1, # 1 or 2 (ref 12)
542
+ },
543
+ # 0xa20c => 'undef', # SpatialFrequencyResponse
544
+ 0xa20e => 'rational64u',# FocalPlaneXResolution
545
+ 0xa20f => 'rational64u',# FocalPlaneYResolution
546
+ 0xa210 => 'int16u', # FocalPlaneResolutionUnit
547
+ 0xa214 => { # SubjectLocation
548
+ Writable => 'int16u',
549
+ Count => 2,
550
+ },
551
+ 0xa215 => 'rational64u',# ExposureIndex
552
+ 0xa217 => 'int16u', # SensingMethod
553
+ 0xa300 => { # FileSource
554
+ Writable => 'undef',
555
+ ValueConvInv => '($val=~/^\d+$/ and $val < 256) ? chr($val) : $val',
556
+ },
557
+ 0xa301 => { # SceneType
558
+ Writable => 'undef',
559
+ ValueConvInv => 'chr($val)',
560
+ },
561
+ 0xa302 => { # CFAPattern
562
+ Writable => 'undef',
563
+ RawConvInv => q{
564
+ my @a = split ' ', $val;
565
+ return $val if @a <= 2; # also accept binary data for backward compatibility
566
+ return pack(GetByteOrder() eq 'II' ? 'v2C*' : 'n2C*', @a);
567
+ },
568
+ PrintConvInv => 'Image::ExifTool::Exif::GetCFAPattern($val)',
569
+ },
570
+ 0xa401 => 'int16u', # CustomRendered
571
+ 0xa402 => 'int16u', # ExposureMode
572
+ 0xa403 => 'int16u', # WhiteBalance
573
+ 0xa404 => 'rational64u',# DigitalZoomRatio
574
+ 0xa405 => { # FocalLengthIn35mmFormat
575
+ Writable => 'int16u',
576
+ PrintConvInv => '$val=~s/\s*mm$//;$val',
577
+ },
578
+ 0xa406 => 'int16u', # SceneCaptureType
579
+ 0xa407 => 'int16u', # GainControl
580
+ 0xa408 => { # Contrast
581
+ Writable => 'int16u',
582
+ PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)',
583
+ },
584
+ 0xa409 => { # Saturation
585
+ Writable => 'int16u',
586
+ PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)',
587
+ },
588
+ 0xa40a => { # Sharpness
589
+ Writable => 'int16u',
590
+ PrintConvInv => 'Image::ExifTool::Exif::ConvertParameter($val)',
591
+ },
592
+ # 0xa40b => 'undef', # DeviceSettingDescription
593
+ 0xa40c => 'int16u', # SubjectDistanceRange
594
+ 0xa420 => 'string', # ImageUniqueID
595
+ 0xa430 => 'string', # OwnerName
596
+ 0xa431 => 'string', # SerialNumber
597
+ 0xa432 => { # LensInfo
598
+ Writable => 'rational64u',
599
+ Count => 4,
600
+ PrintConvInv => \&ConvertLensInfo,
601
+ },
602
+ 0xa433 => 'string', # LensMake
603
+ 0xa434 => 'string', # LensModel
604
+ 0xa435 => 'string', # LensSerialNumber
605
+ 0xa500 => 'rational64u',# Gamma
606
+ #
607
+ # DNG stuff (mostly in IFD0, "Raw IFD" in SubIFD)
608
+ #
609
+ 0xc612 => { # DNGVersion
610
+ Writable => 'int8u',
611
+ WriteGroup => 'IFD0',
612
+ Count => 4,
613
+ Protected => 1, # (confuses Apple Preview if written to a TIFF image)
614
+ PrintConvInv => '$val =~ tr/./ /; $val',
615
+ },
616
+ 0xc613 => { # DNGBackwardVersion
617
+ Writable => 'int8u',
618
+ WriteGroup => 'IFD0',
619
+ Count => 4,
620
+ Protected => 1,
621
+ PrintConvInv => '$val =~ tr/./ /; $val',
622
+ },
623
+ 0xc614 => { # UniqueCameraModel
624
+ Writable => 'string',
625
+ WriteGroup => 'IFD0',
626
+ },
627
+ 0xc615 => { # LocalizedCameraModel
628
+ Writable => 'string',
629
+ WriteGroup => 'IFD0',
630
+ PrintConvInv => '$val',
631
+ },
632
+ 0xc618 => { # LinearizationTable
633
+ Writable => 'int16u',
634
+ WriteGroup => 'SubIFD',
635
+ Count => -1,
636
+ Protected => 1,
637
+ },,
638
+ 0xc619 => { # BlackLevelRepeatDim
639
+ Writable => 'int16u',
640
+ WriteGroup => 'SubIFD',
641
+ Count => 2,
642
+ Protected => 1,
643
+ },
644
+ 0xc61a => { # BlackLevel
645
+ Writable => 'rational64u',
646
+ WriteGroup => 'SubIFD',
647
+ Count => -1,
648
+ Protected => 1,
649
+ },
650
+ 0xc61b => { # BlackLevelDeltaH
651
+ Writable => 'rational64s',
652
+ WriteGroup => 'SubIFD',
653
+ Count => -1,
654
+ Protected => 1,
655
+ },
656
+ 0xc61c => { # BlackLevelDeltaV
657
+ Writable => 'rational64s',
658
+ WriteGroup => 'SubIFD',
659
+ Count => -1,
660
+ Protected => 1,
661
+ },
662
+ 0xc61d => { # WhiteLevel
663
+ Writable => 'int32u',
664
+ WriteGroup => 'SubIFD',
665
+ Count => -1,
666
+ Protected => 1,
667
+ },
668
+ 0xc61e => { # DefaultScale
669
+ Writable => 'rational64u',
670
+ WriteGroup => 'SubIFD',
671
+ Count => 2,
672
+ Protected => 1,
673
+ },
674
+ 0xc61f => { # DefaultCropOrigin
675
+ Writable => 'int32u',
676
+ WriteGroup => 'SubIFD',
677
+ Count => 2,
678
+ Protected => 1,
679
+ },
680
+ 0xc620 => { # DefaultCropSize
681
+ Writable => 'int32u',
682
+ WriteGroup => 'SubIFD',
683
+ Count => 2,
684
+ Protected => 1,
685
+ },
686
+ 0xc621 => { # ColorMatrix1
687
+ Writable => 'rational64s',
688
+ WriteGroup => 'IFD0',
689
+ Count => -1,
690
+ Protected => 1,
691
+ },
692
+ 0xc622 => { # ColorMatrix2
693
+ Writable => 'rational64s',
694
+ WriteGroup => 'IFD0',
695
+ Count => -1,
696
+ Protected => 1,
697
+ },
698
+ 0xc623 => { # CameraCalibration1
699
+ Writable => 'rational64s',
700
+ WriteGroup => 'IFD0',
701
+ Count => -1,
702
+ Protected => 1,
703
+ },
704
+ 0xc624 => { # CameraCalibration2
705
+ Writable => 'rational64s',
706
+ WriteGroup => 'IFD0',
707
+ Count => -1,
708
+ Protected => 1,
709
+ },
710
+ 0xc625 => { # ReductionMatrix1
711
+ Writable => 'rational64s',
712
+ WriteGroup => 'IFD0',
713
+ Count => -1,
714
+ Protected => 1,
715
+ },
716
+ 0xc626 => { # ReductionMatrix2
717
+ Writable => 'rational64s',
718
+ WriteGroup => 'IFD0',
719
+ Count => -1,
720
+ Protected => 1,
721
+ },
722
+ 0xc627 => { # AnalogBalance
723
+ Writable => 'rational64u',
724
+ WriteGroup => 'IFD0',
725
+ Count => -1,
726
+ Protected => 1,
727
+ },
728
+ 0xc628 => { # AsShotNeutral
729
+ Writable => 'rational64u',
730
+ WriteGroup => 'IFD0',
731
+ Count => -1,
732
+ Protected => 1,
733
+ },
734
+ 0xc629 => { # AsShotWhiteXY
735
+ Writable => 'rational64u',
736
+ WriteGroup => 'IFD0',
737
+ Count => 2,
738
+ Protected => 1,
739
+ },
740
+ 0xc62a => { # BaselineExposure
741
+ Writable => 'rational64s',
742
+ WriteGroup => 'IFD0',
743
+ Protected => 1,
744
+ },
745
+ 0xc62b => { # BaselineNoise
746
+ Writable => 'rational64u',
747
+ WriteGroup => 'IFD0',
748
+ Protected => 1,
749
+ },
750
+ 0xc62c => { # BaselineSharpness
751
+ Writable => 'rational64u',
752
+ WriteGroup => 'IFD0',
753
+ Protected => 1,
754
+ },
755
+ 0xc62d => { # BayerGreenSplit
756
+ Writable => 'int32u',
757
+ WriteGroup => 'SubIFD',
758
+ Protected => 1,
759
+ },
760
+ 0xc62e => { # LinearResponseLimit
761
+ Writable => 'rational64u',
762
+ WriteGroup => 'IFD0',
763
+ Protected => 1,
764
+ },
765
+ 0xc62f => { # CameraSerialNumber
766
+ Writable => 'string',
767
+ WriteGroup => 'IFD0',
768
+ },
769
+ 0xc630 => { # DNGLensInfo
770
+ Writable => 'rational64u',
771
+ WriteGroup => 'IFD0',
772
+ Count => 4,
773
+ PrintConvInv => \&ConvertLensInfo,
774
+ },
775
+ 0xc631 => { # ChromaBlurRadius
776
+ Writable => 'rational64u',
777
+ WriteGroup => 'SubIFD',
778
+ Protected => 1,
779
+ },
780
+ 0xc632 => { # AntiAliasStrength
781
+ Writable => 'rational64u',
782
+ WriteGroup => 'SubIFD',
783
+ Protected => 1,
784
+ },
785
+ 0xc633 => { # ShadowScale
786
+ Writable => 'rational64u',
787
+ WriteGroup => 'IFD0',
788
+ Protected => 1,
789
+ },
790
+ 0xc635 => { # MakerNoteSafety
791
+ Writable => 'int16u',
792
+ WriteGroup => 'IFD0',
793
+ },
794
+ 0xc65a => { # CalibrationIlluminant1
795
+ Writable => 'int16u',
796
+ WriteGroup => 'IFD0',
797
+ Protected => 1,
798
+ },
799
+ 0xc65b => { # CalibrationIlluminant2
800
+ Writable => 'int16u',
801
+ WriteGroup => 'IFD0',
802
+ Protected => 1,
803
+ },
804
+ 0xc65c => { # BestQualityScale
805
+ Writable => 'rational64u',
806
+ WriteGroup => 'SubIFD',
807
+ Protected => 1,
808
+ },
809
+ 0xc65d => { # RawDataUniqueID
810
+ Writable => 'int8u',
811
+ WriteGroup => 'IFD0',
812
+ Count => 16,
813
+ Count => 16,
814
+ ValueConvInv => 'pack("H*", $val)',
815
+ Protected => 1,
816
+ },
817
+ 0xc68b => { # OriginalRawFileName
818
+ Writable => 'string',
819
+ WriteGroup => 'IFD0',
820
+ Protected => 1,
821
+ },
822
+ 0xc68d => { # ActiveArea
823
+ Writable => 'int32u',
824
+ WriteGroup => 'SubIFD',
825
+ Count => 4,
826
+ Protected => 1,
827
+ },
828
+ 0xc68e => { # MaskedAreas
829
+ Writable => 'int32u',
830
+ WriteGroup => 'SubIFD',
831
+ Count => 4,
832
+ Protected => 1,
833
+ },
834
+ 0xc68f => { # AsShotICCProfile (writable directory)
835
+ WriteGroup => 'IFD0',
836
+ Protected => 1,
837
+ WriteCheck => q{
838
+ require Image::ExifTool::ICC_Profile;
839
+ return Image::ExifTool::ICC_Profile::ValidateICC(\$val);
840
+ },
841
+ },
842
+ 0xc690 => { # AsShotPreProfileMatrix
843
+ Writable => 'rational64s',
844
+ WriteGroup => 'IFD0',
845
+ Count => -1,
846
+ Protected => 1,
847
+ },
848
+ 0xc691 => { # CurrentICCProfile (writable directory)
849
+ Writable => 'undef',
850
+ WriteGroup => 'IFD0',
851
+ Protected => 1,
852
+ WriteCheck => q{
853
+ require Image::ExifTool::ICC_Profile;
854
+ return Image::ExifTool::ICC_Profile::ValidateICC(\$val);
855
+ },
856
+ },
857
+ 0xc692 => { # CurrentPreProfileMatrix
858
+ Writable => 'rational64s',
859
+ WriteGroup => 'IFD0',
860
+ Count => -1,
861
+ Protected => 1,
862
+ },
863
+ 0xc6bf => { # ColorimetricReference
864
+ Writable => 'int16u',
865
+ WriteGroup => 'IFD0',
866
+ Protected => 1,
867
+ },
868
+ 0xc6d2 => { # PanasonicTitle (Panasonic DMC-TZ5, not a DNG tag)
869
+ Writable => 'undef',
870
+ WriteGroup => 'IFD0',
871
+ ValueConvInv => '$self->Encode($val,"UTF8")',
872
+ },
873
+ 0xc6d3 => { # PanasonicTitle2 (Panasonic DMC-FS7, not a DNG tag)
874
+ Writable => 'undef',
875
+ WriteGroup => 'IFD0',
876
+ ValueConvInv => '$self->Encode($val,"UTF8")',
877
+ },
878
+ 0xc6f3 => { # CameraCalibrationSig
879
+ Writable => 'string',
880
+ WriteGroup => 'IFD0',
881
+ Protected => 1,
882
+ },
883
+ 0xc6f4 => { # ProfileCalibrationSig
884
+ Writable => 'string',
885
+ WriteGroup => 'IFD0',
886
+ Protected => 1,
887
+ },
888
+ 0xc6f6 => { # AsShotProfileName
889
+ Writable => 'string',
890
+ WriteGroup => 'IFD0',
891
+ Protected => 1,
892
+ },
893
+ 0xc6f7 => { # NoiseReductionApplied
894
+ Writable => 'rational64u',
895
+ WriteGroup => 'SubIFD',
896
+ Protected => 1,
897
+ },
898
+ 0xc6f8 => { # ProfileName
899
+ Writable => 'string',
900
+ WriteGroup => 'IFD0',
901
+ Protected => 1,
902
+ },
903
+ 0xc6f9 => { # ProfileHueSatMapDims
904
+ Writable => 'int32u',
905
+ WriteGroup => 'IFD0',
906
+ Count => 3,
907
+ Protected => 1,
908
+ },
909
+ 0xc6fa => { # ProfileHueSatMapData1
910
+ Writable => 'float',
911
+ WriteGroup => 'IFD0',
912
+ Count => -1,
913
+ Protected => 1,
914
+ },
915
+ 0xc6fb => { # ProfileHueSatMapData2
916
+ Writable => 'float',
917
+ WriteGroup => 'IFD0',
918
+ Count => -1,
919
+ Protected => 1,
920
+ },
921
+ 0xc6fc => { # ProfileToneCurve
922
+ Writable => 'float',
923
+ WriteGroup => 'IFD0',
924
+ Count => -1,
925
+ Protected => 1,
926
+ },
927
+ 0xc6fd => { # ProfileEmbedPolicy
928
+ Writable => 'int32u',
929
+ WriteGroup => 'IFD0',
930
+ Protected => 1,
931
+ },
932
+ 0xc6fe => { # ProfileCopyright
933
+ Writable => 'string',
934
+ WriteGroup => 'IFD0',
935
+ Protected => 1,
936
+ },
937
+ 0xc714 => { # ForwardMatrix1
938
+ Writable => 'rational64s',
939
+ WriteGroup => 'IFD0',
940
+ Count => -1,
941
+ Protected => 1,
942
+ },
943
+ 0xc715 => { # ForwardMatrix2
944
+ Writable => 'rational64s',
945
+ WriteGroup => 'IFD0',
946
+ Count => -1,
947
+ Protected => 1,
948
+ },
949
+ 0xc716 => { # PreviewApplicationName
950
+ Writable => 'string',
951
+ WriteGroup => 'IFD0',
952
+ Protected => 1,
953
+ },
954
+ 0xc717 => { # PreviewApplicationVersion
955
+ Writable => 'string',
956
+ WriteGroup => 'IFD0',
957
+ Protected => 1,
958
+ },
959
+ 0xc718 => { # PreviewSettingsName
960
+ Writable => 'string',
961
+ WriteGroup => 'IFD0',
962
+ Protected => 1,
963
+ },
964
+ 0xc719 => { # PreviewSettingsDigest
965
+ Writable => 'int8u',
966
+ WriteGroup => 'IFD0',
967
+ Protected => 1,
968
+ ValueConvInv => 'pack("H*", $val)',
969
+ },
970
+ 0xc71a => { # PreviewColorSpace
971
+ Writable => 'int32u',
972
+ WriteGroup => 'IFD0',
973
+ Protected => 1,
974
+ PrintConv => {
975
+ 0 => 'Unknown',
976
+ 1 => 'Gray Gamma 2.2',
977
+ 2 => 'sRGB',
978
+ 3 => 'Adobe RGB',
979
+ 4 => 'ProPhoto RGB',
980
+ },
981
+ },
982
+ 0xc71b => { # PreviewDateTime
983
+ Writable => 'string',
984
+ WriteGroup => 'IFD0',
985
+ Protected => 1,
986
+ ValueConvInv => q{
987
+ require Image::ExifTool::XMP;
988
+ return Image::ExifTool::XMP::FormatXMPDate($val);
989
+ },
990
+ PrintConvInv => '$self->InverseDateTime($val,1,1)',
991
+ },
992
+ 0xc71c => { # RawImageDigest
993
+ Writable => 'int8u',
994
+ WriteGroup => 'IFD0',
995
+ Count => 16,
996
+ Protected => 1,
997
+ ValueConvInv => 'pack("H*", $val)',
998
+ },
999
+ 0xc71d => { # OriginalRawFileDigest
1000
+ Writable => 'int8u',
1001
+ WriteGroup => 'IFD0',
1002
+ Count => 16,
1003
+ Protected => 1,
1004
+ ValueConvInv => 'pack("H*", $val)',
1005
+ },
1006
+ 0xc725 => { # ProfileLookTableDims
1007
+ Writable => 'int32u',
1008
+ WriteGroup => 'IFD0',
1009
+ Count => 3,
1010
+ Protected => 1,
1011
+ },
1012
+ 0xc726 => { # ProfileLookTableData
1013
+ Writable => 'float',
1014
+ WriteGroup => 'IFD0',
1015
+ Count => -1,
1016
+ Protected => 1,
1017
+ },
1018
+ 0xc761 => { # NoiseProfile
1019
+ Writable => 'double',
1020
+ WriteGroup => 'SubIFD',
1021
+ Count => -1,
1022
+ Protected => 1,
1023
+ },
1024
+ 0xc763 => { # TimeCodes
1025
+ Writable => 'int8u',
1026
+ WriteGroup => 'IFD0',
1027
+ Count => -1, # (8 * number of time codes, max 10)
1028
+ ValueConvInv => q{
1029
+ my @a = map hex, split /[. ]+/, $val;
1030
+ join ' ', @a;
1031
+ },
1032
+ PrintConvInv => q{
1033
+ my @a = split ' ', $val;
1034
+ my @v;
1035
+ foreach (@a) {
1036
+ my @td = reverse split /T/;
1037
+ my $tz = 0x39; # default to unknown timezone
1038
+ if ($td[0] =~ s/([-+])(\d+):(\d+)$//) {
1039
+ if ($3 == 0) {
1040
+ $tz = hex(($1 eq '-') ? $2 : 0x26 - $2);
1041
+ } elsif ($3 == 30) {
1042
+ if ($1 eq '-') {
1043
+ $tz = $2 + 0x0a;
1044
+ $tz += 0x0a if $tz > 0x0f;
1045
+ } else {
1046
+ $tz = 0x3f - $2;
1047
+ $tz -= 0x0a if $tz < 0x3a;
1048
+ }
1049
+ } elsif ($3 == 45) {
1050
+ $tz = 0x32 if $1 eq '+' and $2 == 12;
1051
+ }
1052
+ }
1053
+ my @t = split /[:.]/, $td[0];
1054
+ push @t, '00' while @t < 4;
1055
+ my $bg;
1056
+ if ($td[1]) {
1057
+ # date was specified: fill in date & timezone
1058
+ my @d = split /[-]/, $td[1];
1059
+ next if @d < 3;
1060
+ $bg = sprintf('.%.2d.%.2d.%.2d.%.2x', $d[2], $d[1], $d[0]%100, $tz);
1061
+ $t[0] = sprintf('%.2x', hex($t[0]) + 0xc0); # set BGF1+BGF2
1062
+ } else { # time only
1063
+ $bg = '.00.00.00.00';
1064
+ }
1065
+ push @v, join('.', reverse(@t[0..3])) . $bg;
1066
+ }
1067
+ join ' ', @v;
1068
+ },
1069
+ },
1070
+ 0xc764 => { # FrameRate
1071
+ Writable => 'rational64s',
1072
+ WriteGroup => 'IFD0',
1073
+ PrintConvInv => '$val',
1074
+ },
1075
+ 0xc772 => { # TStop
1076
+ Writable => 'rational64u',
1077
+ WriteGroup => 'IFD0',
1078
+ Count => -1, # (1 or 2)
1079
+ PrintConvInv => '$val=~tr/-/ /; $val',
1080
+ },
1081
+ 0xc789 => { # ReelName
1082
+ Writable => 'string',
1083
+ WriteGroup => 'IFD0',
1084
+ },
1085
+ 0xc791 => { # OriginalDefaultFinalSize
1086
+ Writable => 'int32u',
1087
+ WriteGroup => 'IFD0',
1088
+ Count => 2,
1089
+ Protected => 1,
1090
+ },
1091
+ 0xc792 => { # OriginalBestQualitySize
1092
+ Writable => 'int32u',
1093
+ WriteGroup => 'IFD0',
1094
+ Count => 2,
1095
+ Protected => 1,
1096
+ },
1097
+ 0xc793 => { # OriginalDefaultCropSize
1098
+ Writable => 'rational64u',
1099
+ WriteGroup => 'IFD0',
1100
+ Count => 2,
1101
+ Protected => 1,
1102
+ },
1103
+ 0xc7a1 => { # CameraLabel
1104
+ Writable => 'string',
1105
+ WriteGroup => 'IFD0',
1106
+ },
1107
+ 0xc7a3 => { # ProfileHueSatMapEncoding
1108
+ Writable => 'int32u',
1109
+ WriteGroup => 'IFD0',
1110
+ Protected => 1,
1111
+ },
1112
+ 0xc7a4 => { # ProfileLookTableEncoding
1113
+ Writable => 'int32u',
1114
+ WriteGroup => 'IFD0',
1115
+ Protected => 1,
1116
+ },
1117
+ 0xc7a5 => { # BaselineExposureOffset
1118
+ Writable => 'rational64u',
1119
+ WriteGroup => 'IFD0',
1120
+ Protected => 1,
1121
+ },
1122
+ 0xc7a6 => { # DefaultBlackRender
1123
+ Writable => 'int32u',
1124
+ WriteGroup => 'IFD0',
1125
+ Protected => 1,
1126
+ },
1127
+ 0xc7a7 => { # NewRawImageDigest
1128
+ Writable => 'int8u',
1129
+ WriteGroup => 'IFD0',
1130
+ Count => 16,
1131
+ Protected => 1,
1132
+ ValueConvInv => 'pack("H*", $val)',
1133
+ },
1134
+ 0xc7a8 => { # RawToPreviewGain
1135
+ Writable => 'double',
1136
+ WriteGroup => 'IFD0',
1137
+ Protected => 1,
1138
+ },
1139
+ 0xc7b5 => { # DefaultUserCrop
1140
+ Writable => 'rational64u',
1141
+ WriteGroup => 'SubIFD',
1142
+ Count => 4,
1143
+ Protected => 1,
1144
+ },
1145
+ # --- end DNG tags ---
1146
+ 0xea1d => { # OffsetSchema
1147
+ Writable => 'int32s',
1148
+ },
1149
+ # tags produced by Photoshop Camera RAW
1150
+ # (avoid creating these tags unless there is no other option)
1151
+ 0xfde8 => {
1152
+ Name => 'OwnerName',
1153
+ Condition => '$$self{TIFF_TYPE} ne "DCR"', # (used for another purpose in Kodak DCR images)
1154
+ Avoid => 1,
1155
+ PSRaw => 1,
1156
+ Writable => 'string',
1157
+ ValueConv => '$val=~s/^.*: //;$val',
1158
+ ValueConvInv => q{"Owner's Name: $val"},
1159
+ Notes => q{
1160
+ tags 0xfde8-0xfdea and 0xfe4c-0xfe58 are generated by Photoshop Camera RAW.
1161
+ Some names are the same as other EXIF tags, but ExifTool will avoid writing
1162
+ these unless they already exist in the file
1163
+ },
1164
+ },
1165
+ 0xfde9 => {
1166
+ Name => 'SerialNumber',
1167
+ Condition => '$$self{TIFF_TYPE} ne "DCR"', # (used for another purpose in Kodak DCR SubIFD)
1168
+ Avoid => 1,
1169
+ PSRaw => 1,
1170
+ Writable => 'string',
1171
+ ValueConv => '$val=~s/^.*: //;$val',
1172
+ ValueConvInv => q{"Serial Number: $val"},
1173
+ },
1174
+ 0xfdea => {
1175
+ Name => 'Lens',
1176
+ Condition => '$$self{TIFF_TYPE} ne "DCR"', # (used for another purpose in Kodak DCR SubIFD)
1177
+ Avoid => 1,
1178
+ PSRaw => 1,
1179
+ Writable => 'string',
1180
+ ValueConv => '$val=~s/^.*: //;$val',
1181
+ ValueConvInv => q{"Lens: $val"},
1182
+ },
1183
+ 0xfe4c => {
1184
+ Name => 'RawFile',
1185
+ Avoid => 1,
1186
+ PSRaw => 1,
1187
+ Writable => 'string',
1188
+ ValueConv => '$val=~s/^.*: //;$val',
1189
+ ValueConvInv => q{"Raw File: $val"},
1190
+ },
1191
+ 0xfe4d => {
1192
+ Name => 'Converter',
1193
+ Avoid => 1,
1194
+ PSRaw => 1,
1195
+ Writable => 'string',
1196
+ ValueConv => '$val=~s/^.*: //;$val',
1197
+ ValueConvInv => q{"Converter: $val"},
1198
+ },
1199
+ 0xfe4e => {
1200
+ Name => 'WhiteBalance',
1201
+ Avoid => 1,
1202
+ PSRaw => 1,
1203
+ Writable => 'string',
1204
+ ValueConv => '$val=~s/^.*: //;$val',
1205
+ ValueConvInv => q{"White Balance: $val"},
1206
+ },
1207
+ 0xfe51 => {
1208
+ Name => 'Exposure',
1209
+ Avoid => 1,
1210
+ PSRaw => 1,
1211
+ Writable => 'string',
1212
+ ValueConv => '$val=~s/^.*: //;$val',
1213
+ ValueConvInv => q{"Exposure: $val"},
1214
+ },
1215
+ 0xfe52 => {
1216
+ Name => 'Shadows',
1217
+ Avoid => 1,
1218
+ PSRaw => 1,
1219
+ Writable => 'string',
1220
+ ValueConv => '$val=~s/^.*: //;$val',
1221
+ ValueConvInv => q{"Shadows: $val"},
1222
+ },
1223
+ 0xfe53 => {
1224
+ Name => 'Brightness',
1225
+ Avoid => 1,
1226
+ PSRaw => 1,
1227
+ Writable => 'string',
1228
+ ValueConv => '$val=~s/^.*: //;$val',
1229
+ ValueConvInv => q{"Brightness: $val"},
1230
+ },
1231
+ 0xfe54 => {
1232
+ Name => 'Contrast',
1233
+ Avoid => 1,
1234
+ PSRaw => 1,
1235
+ Writable => 'string',
1236
+ ValueConv => '$val=~s/^.*: //;$val',
1237
+ ValueConvInv => q{"Contrast: $val"},
1238
+ },
1239
+ 0xfe55 => {
1240
+ Name => 'Saturation',
1241
+ Avoid => 1,
1242
+ PSRaw => 1,
1243
+ Writable => 'string',
1244
+ ValueConv => '$val=~s/^.*: //;$val',
1245
+ ValueConvInv => q{"Saturation: $val"},
1246
+ },
1247
+ 0xfe56 => {
1248
+ Name => 'Sharpness',
1249
+ Avoid => 1,
1250
+ PSRaw => 1,
1251
+ Writable => 'string',
1252
+ ValueConv => '$val=~s/^.*: //;$val',
1253
+ ValueConvInv => q{"Sharpness: $val"},
1254
+ },
1255
+ 0xfe57 => {
1256
+ Name => 'Smoothness',
1257
+ Avoid => 1,
1258
+ PSRaw => 1,
1259
+ Writable => 'string',
1260
+ ValueConv => '$val=~s/^.*: //;$val',
1261
+ ValueConvInv => q{"Smoothness: $val"},
1262
+ },
1263
+ 0xfe58 => {
1264
+ Name => 'MoireFilter',
1265
+ Avoid => 1,
1266
+ PSRaw => 1,
1267
+ Writable => 'string',
1268
+ ValueConv => '$val=~s/^.*: //;$val',
1269
+ ValueConvInv => q{"Moire Filter: $val"},
1270
+ },
1271
+ );
1272
+
1273
+ # insert our writable properties into main EXIF tag table
1274
+ InsertWritableProperties(\%Image::ExifTool::Exif::Main, \%writeTable, \&CheckExif);
1275
+
1276
+ #------------------------------------------------------------------------------
1277
+ # Inverse print conversion for LensInfo
1278
+ # Inputs: 0) lens info string
1279
+ # Returns: PrintConvInv of string
1280
+ sub ConvertLensInfo($)
1281
+ {
1282
+ my $val = shift;
1283
+ my @a = GetLensInfo($val, 1); # (allow unknown "?" values)
1284
+ return @a ? join(' ', @a) : $val;
1285
+ }
1286
+
1287
+ #------------------------------------------------------------------------------
1288
+ # Get binary CFA Pattern from a text string
1289
+ # Inputs: Print-converted CFA pattern (ie. '[Blue,Green][Green,Red]')
1290
+ # Returns: CFA pattern as a string of numbers
1291
+ sub GetCFAPattern($)
1292
+ {
1293
+ my $val = shift;
1294
+ my @rows = split /\]\s*\[/, $val;
1295
+ @rows or warn("Rows not properly bracketed by '[]'\n"), return undef;
1296
+ my @cols = split /,/, $rows[0];
1297
+ @cols or warn("Colors not separated by ','\n"), return undef;
1298
+ my $ny = @cols;
1299
+ my @a = (scalar(@rows), scalar(@cols));
1300
+ my %cfaLookup = (red=>0, green=>1, blue=>2, cyan=>3, magenta=>4, yellow=>5, white=>6);
1301
+ my $row;
1302
+ foreach $row (@rows) {
1303
+ @cols = split /,/, $row;
1304
+ @cols == $ny or warn("Inconsistent number of colors in each row\n"), return undef;
1305
+ foreach (@cols) {
1306
+ tr/ \]\[//d; # remove remaining brackets and any spaces
1307
+ my $c = $cfaLookup{lc($_)};
1308
+ defined $c or warn("Unknown color '$_'\n"), return undef;
1309
+ push @a, $c;
1310
+ }
1311
+ }
1312
+ return "@a";
1313
+ }
1314
+
1315
+ #------------------------------------------------------------------------------
1316
+ # validate raw values for writing
1317
+ # Inputs: 0) ExifTool ref, 1) tagInfo hash ref, 2) raw value ref
1318
+ # Returns: error string or undef (and possibly changes value) on success
1319
+ sub CheckExif($$$)
1320
+ {
1321
+ my ($exifTool, $tagInfo, $valPtr) = @_;
1322
+ my $format = $$tagInfo{Format} || $$tagInfo{Writable} || $tagInfo->{Table}{WRITABLE};
1323
+ if (not $format or $format eq '1') {
1324
+ if ($tagInfo->{Groups}{0} eq 'MakerNotes') {
1325
+ return undef; # OK to have no format for makernotes
1326
+ } else {
1327
+ return 'No writable format';
1328
+ }
1329
+ }
1330
+ return Image::ExifTool::CheckValue($valPtr, $format, $$tagInfo{Count});
1331
+ }
1332
+
1333
+ #------------------------------------------------------------------------------
1334
+ # encode exif ASCII/Unicode text from UTF8 or Latin
1335
+ # Inputs: 0) ExifTool ref, 1) text string
1336
+ # Returns: encoded string
1337
+ # Note: MUST be called Raw conversion time so the EXIF byte order is known!
1338
+ sub EncodeExifText($$)
1339
+ {
1340
+ my ($exifTool, $val) = @_;
1341
+ # does the string contain special characters?
1342
+ if ($val =~ /[\x80-\xff]/) {
1343
+ my $order = $exifTool->GetNewValues('ExifUnicodeByteOrder');
1344
+ return "UNICODE\0" . $exifTool->Encode($val,'UTF16',$order);
1345
+ } else {
1346
+ return "ASCII\0\0\0$val";
1347
+ }
1348
+ }
1349
+
1350
+ #------------------------------------------------------------------------------
1351
+ # insert writable properties into main tag table
1352
+ # Inputs: 0) tag table ref, 1) reference to writable properties
1353
+ # 2) [optional] CHECK_PROC reference
1354
+ sub InsertWritableProperties($$;$)
1355
+ {
1356
+ my ($tagTablePtr, $writeTablePtr, $checkProc) = @_;
1357
+ my $tag;
1358
+ $checkProc and $tagTablePtr->{CHECK_PROC} = $checkProc;
1359
+ foreach $tag (keys %$writeTablePtr) {
1360
+ my $writeInfo = $$writeTablePtr{$tag};
1361
+ my @infoList = GetTagInfoList($tagTablePtr, $tag);
1362
+ if (@infoList) {
1363
+ my $tagInfo;
1364
+ foreach $tagInfo (@infoList) {
1365
+ if (ref $writeInfo) {
1366
+ my $key;
1367
+ foreach $key (keys %$writeInfo) {
1368
+ $$tagInfo{$key} = $$writeInfo{$key} unless defined $$tagInfo{$key};
1369
+ }
1370
+ } else {
1371
+ $$tagInfo{Writable} = $writeInfo unless defined $$tagInfo{Writable};
1372
+ }
1373
+ }
1374
+ } else {
1375
+ AddTagToTable($tagTablePtr, $tag, $writeInfo);
1376
+ }
1377
+ }
1378
+ }
1379
+
1380
+ #------------------------------------------------------------------------------
1381
+ # rebuild maker notes to properly contain all value data
1382
+ # (some manufacturers put value data outside maker notes!!)
1383
+ # Inputs: 0) ExifTool object ref, 1) tag table ref, 2) dirInfo ref
1384
+ # Returns: new maker note data (and creates MAKER_NOTE_FIXUP), or undef on error
1385
+ sub RebuildMakerNotes($$$)
1386
+ {
1387
+ my ($exifTool, $tagTablePtr, $dirInfo) = @_;
1388
+ my $dirStart = $$dirInfo{DirStart};
1389
+ my $dirLen = $$dirInfo{DirLen};
1390
+ my $dataPt = $$dirInfo{DataPt};
1391
+ my $dataPos = $$dirInfo{DataPos} || 0;
1392
+ my $rtnValue;
1393
+ my %subdirInfo = %$dirInfo;
1394
+
1395
+ delete $exifTool->{MAKER_NOTE_FIXUP};
1396
+
1397
+ # don't need to rebuild text, BinaryData or PreviewImage maker notes
1398
+ my $tagInfo = $$dirInfo{TagInfo};
1399
+ my $subdir = $$tagInfo{SubDirectory};
1400
+ my $proc = $$subdir{ProcessProc} || $$tagTablePtr{PROCESS_PROC} || \&ProcessExif;
1401
+ if (($proc ne \&ProcessExif and $$tagInfo{Name} =~ /Text/) or
1402
+ $proc eq \&Image::ExifTool::ProcessBinaryData or
1403
+ ($$tagInfo{PossiblePreview} and $dirLen > 6 and
1404
+ substr($$dataPt, $dirStart, 3) eq "\xff\xd8\xff"))
1405
+ {
1406
+ return substr($$dataPt, $dirStart, $dirLen);
1407
+ }
1408
+ my $saveOrder = GetByteOrder();
1409
+ my $loc = Image::ExifTool::MakerNotes::LocateIFD($exifTool,\%subdirInfo);
1410
+ if (defined $loc) {
1411
+ my $makerFixup = $subdirInfo{Fixup} = new Image::ExifTool::Fixup;
1412
+ # create new exiftool object to rewrite the directory without changing it
1413
+ my $newTool = new Image::ExifTool;
1414
+ $newTool->Options(
1415
+ IgnoreMinorErrors => $$exifTool{OPTIONS}{IgnoreMinorErrors},
1416
+ FixBase => $$exifTool{OPTIONS}{FixBase},
1417
+ );
1418
+ $newTool->Init(); # must do this before calling WriteDirectory()!
1419
+ # don't copy over preview image
1420
+ $newTool->SetNewValue(PreviewImage => '');
1421
+ # copy all transient members over in case they are used for writing
1422
+ # (Make, Model, etc)
1423
+ foreach (grep /[a-z]/, keys %$exifTool) {
1424
+ $$newTool{$_} = $$exifTool{$_};
1425
+ }
1426
+ # fix base offsets if specified
1427
+ $newTool->Options(FixBase => $exifTool->Options('FixBase'));
1428
+ # set GENERATE_PREVIEW_INFO flag so PREVIEW_INFO will be generated
1429
+ $newTool->{GENERATE_PREVIEW_INFO} = 1;
1430
+ # drop any large tags
1431
+ $newTool->{DROP_TAGS} = 1;
1432
+ # initialize other necessary data members
1433
+ $newTool->{FILE_TYPE} = $exifTool->{FILE_TYPE};
1434
+ $newTool->{TIFF_TYPE} = $exifTool->{TIFF_TYPE};
1435
+ # rewrite maker notes
1436
+ $rtnValue = $newTool->WriteDirectory(\%subdirInfo, $tagTablePtr);
1437
+ if (defined $rtnValue and length $rtnValue) {
1438
+ # add the dummy/empty preview image if necessary
1439
+ if ($newTool->{PREVIEW_INFO}) {
1440
+ $makerFixup->SetMarkerPointers(\$rtnValue, 'PreviewImage', length($rtnValue));
1441
+ $rtnValue .= $newTool->{PREVIEW_INFO}{Data};
1442
+ delete $newTool->{PREVIEW_INFO};
1443
+ }
1444
+ # add makernote header
1445
+ if ($loc) {
1446
+ my $hdr = substr($$dataPt, $dirStart, $loc);
1447
+ # special case: convert Pentax/Samsung DNG maker notes to JPEG style
1448
+ # (in JPEG, Pentax makernotes are absolute and start with "AOC\0")
1449
+ if ($hdr =~ s/^(PENTAX |SAMSUNG)\0/AOC\0/) {
1450
+ # save fixup so we will adjust to absolute offsets when writing
1451
+ $exifTool->{MAKER_NOTE_FIXUP} = $makerFixup;
1452
+ }
1453
+ $rtnValue = $hdr . $rtnValue;
1454
+ # adjust fixup for shift in start position
1455
+ $makerFixup->{Start} += length $hdr;
1456
+ }
1457
+ # shift offsets according to original position of maker notes,
1458
+ # and relative to the makernotes Base
1459
+ $makerFixup->{Shift} += $dataPos + $dirStart +
1460
+ $$dirInfo{Base} - $subdirInfo{Base};
1461
+ # repair incorrect offsets if offsets were fixed
1462
+ $makerFixup->{Shift} += $subdirInfo{FixedBy} || 0;
1463
+ # fix up pointers to the specified offset
1464
+ $makerFixup->ApplyFixup(\$rtnValue);
1465
+ # save fixup information unless offsets were relative
1466
+ unless ($subdirInfo{Relative}) {
1467
+ # set shift so offsets are all relative to start of maker notes
1468
+ $makerFixup->{Shift} -= $dataPos + $dirStart;
1469
+ $exifTool->{MAKER_NOTE_FIXUP} = $makerFixup; # save fixup for later
1470
+ }
1471
+ }
1472
+ }
1473
+ SetByteOrder($saveOrder);
1474
+
1475
+ return $rtnValue;
1476
+ }
1477
+
1478
+ #------------------------------------------------------------------------------
1479
+ # Sort IFD directory entries
1480
+ # Inputs: 0) data reference, 1) directory start, 2) number of entries
1481
+ sub SortIFD($$$)
1482
+ {
1483
+ my ($dataPt, $dirStart, $numEntries) = @_;
1484
+ my ($index, %entries);
1485
+ # split the directory into separate entries
1486
+ my $newDir = '';
1487
+ for ($index=0; $index<$numEntries; ++$index) {
1488
+ my $entry = $dirStart + 2 + 12 * $index;
1489
+ my $tagID = Get16u($dataPt, $entry);
1490
+ my $entryData = substr($$dataPt, $entry, 12);
1491
+ # silly software can pad directories with zero entries -- put these at the end
1492
+ $tagID = 0x10000 unless $tagID or $index == 0;
1493
+ # add new entry (allow for duplicate tag ID's, which shouldn't normally happen)
1494
+ if ($entries{$tagID}) {
1495
+ $entries{$tagID} .= $entryData;
1496
+ } else {
1497
+ $entries{$tagID} = $entryData;
1498
+ }
1499
+ }
1500
+ # sort the directory entries
1501
+ my @sortedTags = sort { $a <=> $b } keys %entries;
1502
+ foreach (@sortedTags) {
1503
+ $newDir .= $entries{$_};
1504
+ }
1505
+ # replace original directory with new, sorted one
1506
+ substr($$dataPt, $dirStart + 2, 12 * $numEntries) = $newDir;
1507
+ }
1508
+
1509
+ #------------------------------------------------------------------------------
1510
+ # Validate IFD entries (strict validation to test possible chained IFD's)
1511
+ # Inputs: 0) dirInfo ref (must have RAF set), 1) optional DirStart
1512
+ # Returns: true if IFD looks OK
1513
+ sub ValidateIFD($;$)
1514
+ {
1515
+ my ($dirInfo, $dirStart) = @_;
1516
+ my $raf = $$dirInfo{RAF} or return 0;
1517
+ my $base = $$dirInfo{Base};
1518
+ $dirStart = $$dirInfo{DirStart} || 0 unless defined $dirStart;
1519
+ my $offset = $dirStart + ($$dirInfo{DataPos} || 0);
1520
+ my ($buff, $index);
1521
+ $raf->Seek($offset + $base, 0) and $raf->Read($buff,2) == 2 or return 0;
1522
+ my $numEntries = Get16u(\$buff,0);
1523
+ $numEntries > 1 and $numEntries < 64 or return 0;
1524
+ my $len = 12 * $numEntries;
1525
+ $raf->Read($buff, $len) == $len or return 0;
1526
+ my $lastID = -1;
1527
+ for ($index=0; $index<$numEntries; ++$index) {
1528
+ my $entry = 12 * $index;
1529
+ my $tagID = Get16u(\$buff, $entry);
1530
+ $tagID > $lastID or $$dirInfo{AllowOutOfOrderTags} or return 0;
1531
+ my $format = Get16u(\$buff, $entry+2);
1532
+ $format > 0 and $format <= 13 or return 0;
1533
+ my $count = Get32u(\$buff, $entry+4);
1534
+ $count > 0 or return 0;
1535
+ $lastID = $tagID;
1536
+ }
1537
+ return 1;
1538
+ }
1539
+
1540
+ #------------------------------------------------------------------------------
1541
+ # Get sorted list of offsets used in IFD
1542
+ # Inputs: 0) data ref, 1) directory start, 2) dataPos, 3) IFD entries, 4) tag table ref
1543
+ # Returns: 0) sorted list of offsets (only offsets after the end of the IFD)
1544
+ # 1) hash of list indices keyed by offset value
1545
+ # Notes: This is used in a patch to fix the count for tags in Kodak SubIFD3
1546
+ sub GetOffList($$$$$)
1547
+ {
1548
+ my ($dataPt, $dirStart, $dataPos, $numEntries, $tagTablePtr) = @_;
1549
+ my $ifdEnd = $dirStart + 2 + 12 * $numEntries + $dataPos;
1550
+ my ($index, $offset, %offHash);
1551
+ for ($index=0; $index<$numEntries; ++$index) {
1552
+ my $entry = $dirStart + 2 + 12 * $index;
1553
+ my $format = Get16u($dataPt, $entry + 2);
1554
+ next if $format < 1 or $format > 13;
1555
+ my $count = Get16u($dataPt, $entry + 4);
1556
+ my $size = $formatSize[$format] * $count;
1557
+ if ($size <= 4) {
1558
+ my $tagID = Get16u($dataPt, $entry);
1559
+ next unless ref $$tagTablePtr{$tagID} eq 'HASH' and $$tagTablePtr{$tagID}{FixCount};
1560
+ }
1561
+ my $offset = Get16u($dataPt, $entry + 8);
1562
+ $offHash{$offset} = 1 if $offset >= $ifdEnd;
1563
+ }
1564
+ # set offset hash values to indices in list
1565
+ my @offList = sort keys %offHash;
1566
+ $index = 0;
1567
+ foreach $offset (@offList) {
1568
+ $offHash{$offset} = $index++;
1569
+ }
1570
+ return(\@offList, \%offHash);
1571
+ }
1572
+
1573
+ #------------------------------------------------------------------------------
1574
+ # Update TIFF_END member if defined
1575
+ # Inputs: 0) ExifTool ref, 1) end of valid TIFF data
1576
+ sub UpdateTiffEnd($$)
1577
+ {
1578
+ my ($exifTool, $end) = @_;
1579
+ if (defined $exifTool->{TIFF_END} and
1580
+ $exifTool->{TIFF_END} < $end)
1581
+ {
1582
+ $exifTool->{TIFF_END} = $end;
1583
+ }
1584
+ }
1585
+
1586
+ #------------------------------------------------------------------------------
1587
+ # Handle error while writing EXIF
1588
+ # Inputs: 0) ExifTool ref, 1) error string, 2) tag table ref
1589
+ # Returns: undef on fatal error, or '' if minor error is ignored
1590
+ sub ExifErr($$$)
1591
+ {
1592
+ my ($exifTool, $errStr, $tagTablePtr) = @_;
1593
+ # MakerNote errors are minor by default
1594
+ my $minor = ($tagTablePtr->{GROUPS}{0} eq 'MakerNotes');
1595
+ if ($tagTablePtr->{VARS} and $tagTablePtr->{VARS}{MINOR_ERRORS}) {
1596
+ $exifTool->Warn("$errStr. IFD dropped.") and return '' if $minor;
1597
+ $minor = 1;
1598
+ }
1599
+ return undef if $exifTool->Error($errStr, $minor);
1600
+ return '';
1601
+ }
1602
+
1603
+ #------------------------------------------------------------------------------
1604
+ # Read/Write IFD with TIFF-like header (used by DNG 1.2)
1605
+ # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
1606
+ # Returns: Reading: 1 on success, otherwise returns 0 and sets a Warning
1607
+ # Writing: new data block or undef on error
1608
+ sub ProcessTiffIFD($$$)
1609
+ {
1610
+ my ($exifTool, $dirInfo, $tagTablePtr) = @_;
1611
+ $exifTool or return 1; # allow dummy access
1612
+ my $raf = $$dirInfo{RAF};
1613
+ my $base = $$dirInfo{Base} || 0;
1614
+ my $dirName = $$dirInfo{DirName};
1615
+ my $magic = $dirInfo->{Subdir}{Magic} || 0x002a;
1616
+ my $buff;
1617
+
1618
+ # structured with a TIFF-like header and relative offsets
1619
+ $raf->Seek($base, 0) and $raf->Read($buff, 8) == 8 or return 0;
1620
+ unless (SetByteOrder(substr($buff,0,2)) and Get16u(\$buff, 2) == $magic) {
1621
+ my $msg = "Invalid $dirName header";
1622
+ if ($$dirInfo{IsWriting}) {
1623
+ $exifTool->Error($msg);
1624
+ return undef;
1625
+ } else {
1626
+ $exifTool->Warn($msg);
1627
+ return 0;
1628
+ }
1629
+ }
1630
+ my $offset = Get32u(\$buff, 4);
1631
+ my %dirInfo = (
1632
+ DirName => $$dirInfo{DirName},
1633
+ Parent => $$dirInfo{Parent},
1634
+ Base => $base,
1635
+ DataPt => \$buff,
1636
+ DataLen => length $buff,
1637
+ DataPos => 0,
1638
+ DirStart => $offset,
1639
+ DirLen => length($buff) - $offset,
1640
+ RAF => $raf,
1641
+ NewDataPos => 8,
1642
+ );
1643
+ if ($$dirInfo{IsWriting}) {
1644
+ # rewrite the Camera Profile IFD
1645
+ my $newDir = WriteExif($exifTool, \%dirInfo, $tagTablePtr);
1646
+ # don't add header if error writing directory ($newDir is undef)
1647
+ # or if directory is being deleted ($newDir is empty)
1648
+ return $newDir unless $newDir;
1649
+ # return directory with TIFF-like header
1650
+ return GetByteOrder() . Set16u($magic) . Set32u(8) . $newDir;
1651
+ }
1652
+ if ($exifTool->{HTML_DUMP}) {
1653
+ my $tip = sprintf("Byte order: %s endian\nIdentifier: 0x%.4x\n%s offset: 0x%.4x",
1654
+ (GetByteOrder() eq 'II') ? 'Little' : 'Big', $magic, $dirName, $offset);
1655
+ $exifTool->HDump($base, 8, "$dirName header", $tip, 0);
1656
+ }
1657
+ return ProcessExif($exifTool, \%dirInfo, $tagTablePtr);
1658
+ }
1659
+
1660
+ #------------------------------------------------------------------------------
1661
+ # Write EXIF directory
1662
+ # Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref
1663
+ # Returns: Exif data block (may be empty if no Exif data) or undef on error
1664
+ # Notes: Increments ExifTool CHANGED flag for each tag changed. Also updates
1665
+ # TIFF_END if defined with location of end of original TIFF image.
1666
+ # Returns IFD data in the following order:
1667
+ # 1. IFD0 directory followed by its data
1668
+ # 2. SubIFD directory followed by its data, thumbnail and image
1669
+ # 3. GlobalParameters, EXIF, GPS, Interop IFD's each with their data
1670
+ # 4. IFD1,IFD2,... directories each followed by their data
1671
+ # 5. Thumbnail and/or image data for each IFD, with IFD0 image last
1672
+ sub WriteExif($$$)
1673
+ {
1674
+ my ($exifTool, $dirInfo, $tagTablePtr) = @_;
1675
+ $exifTool or return 1; # allow dummy access to autoload this package
1676
+ my $origDirInfo = $dirInfo; # save original dirInfo
1677
+ my $dataPt = $$dirInfo{DataPt};
1678
+ unless ($dataPt) {
1679
+ my $emptyData = '';
1680
+ $dataPt = \$emptyData;
1681
+ }
1682
+ my $dataPos = $$dirInfo{DataPos} || 0;
1683
+ my $dirStart = $$dirInfo{DirStart} || 0;
1684
+ my $dataLen = $$dirInfo{DataLen} || length($$dataPt);
1685
+ my $dirLen = $$dirInfo{DirLen} || ($dataLen - $dirStart);
1686
+ my $base = $$dirInfo{Base} || 0;
1687
+ my $firstBase = $base;
1688
+ my $raf = $$dirInfo{RAF};
1689
+ my $dirName = $$dirInfo{DirName} || 'unknown';
1690
+ my $fixup = $$dirInfo{Fixup} || new Image::ExifTool::Fixup;
1691
+ my $imageDataFlag = $$dirInfo{ImageData} || '';
1692
+ my $verbose = $exifTool->Options('Verbose');
1693
+ my $out = $exifTool->Options('TextOut');
1694
+ my ($nextIfdPos, %offsetData, $inMakerNotes);
1695
+ my (@offsetInfo, %xDelete, $strEnc);
1696
+ my $deleteAll = 0;
1697
+ my $newData = ''; # initialize buffer to receive new directory data
1698
+ my @imageData; # image data blocks to copy later if requested
1699
+ my $name = $$dirInfo{Name};
1700
+ $name = $dirName unless $name and $dirName eq 'MakerNotes' and $name !~ /^MakerNote/;
1701
+
1702
+ # set encoding for strings
1703
+ $strEnc = $exifTool->Options('CharsetEXIF') if $$tagTablePtr{GROUPS}{0} eq 'EXIF';
1704
+
1705
+ # allow multiple IFD's in IFD0-IFD1-IFD2... chain
1706
+ $$dirInfo{Multi} = 1 if $dirName =~ /^(IFD0|SubIFD)$/ and not defined $$dirInfo{Multi};
1707
+ $inMakerNotes = 1 if $tagTablePtr->{GROUPS}{0} eq 'MakerNotes';
1708
+ my $ifd;
1709
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1710
+ # loop through each IFD
1711
+ #
1712
+ for ($ifd=0; ; ++$ifd) { # loop through multiple IFD's
1713
+
1714
+ # save pointer to start of this IFD within the newData
1715
+ my $newStart = length($newData);
1716
+ my @subdirs; # list of subdirectory data and tag table pointers
1717
+ # determine if directory is contained within our data
1718
+ my $mustRead;
1719
+ if ($dirStart < 0 or $dirStart > $dataLen-2) {
1720
+ $mustRead = 1;
1721
+ } elsif ($dirLen > 2) {
1722
+ my $len = 2 + 12 * Get16u($dataPt, $dirStart);
1723
+ $mustRead = 1 if $dirStart + $len > $dataLen;
1724
+ }
1725
+ # read IFD from file if necessary
1726
+ if ($mustRead) {
1727
+ if ($raf) {
1728
+ # read the count of entries in this IFD
1729
+ my $offset = $dirStart + $dataPos;
1730
+ my ($buff, $buf2);
1731
+ unless ($raf->Seek($offset + $base, 0) and $raf->Read($buff,2) == 2) {
1732
+ return ExifErr($exifTool, "Bad IFD or truncated file in $name", $tagTablePtr);
1733
+ }
1734
+ my $len = 12 * Get16u(\$buff,0);
1735
+ # (also read next IFD pointer if available)
1736
+ unless ($raf->Read($buf2, $len+4) >= $len) {
1737
+ return ExifErr($exifTool, "Error reading $name", $tagTablePtr);
1738
+ }
1739
+ $buff .= $buf2;
1740
+ # make copy of dirInfo since we're going to modify it
1741
+ my %newDirInfo = %$dirInfo;
1742
+ $dirInfo = \%newDirInfo;
1743
+ # update directory parameters for the newly loaded IFD
1744
+ $dataPt = $$dirInfo{DataPt} = \$buff;
1745
+ $dirStart = $$dirInfo{DirStart} = 0;
1746
+ $dataPos = $$dirInfo{DataPos} = $offset;
1747
+ $dataLen = $$dirInfo{DataLen} = length $buff;
1748
+ $dirLen = $$dirInfo{DirLen} = $dataLen;
1749
+ # only account for nextIFD pointer if we are going to use it
1750
+ $len += 4 if $dataLen==$len+6 and ($$dirInfo{Multi} or $buff =~ /\0{4}$/);
1751
+ UpdateTiffEnd($exifTool, $offset+$base+2+$len);
1752
+ } elsif ($dirLen) {
1753
+ # error if we can't load IFD (unless we are creating
1754
+ # from scratch, in which case dirLen will be zero)
1755
+ my $str = $exifTool->Options('IgnoreMinorErrors') ? 'Deleted bad' : 'Bad';
1756
+ $exifTool->Error("$str $name directory", 1);
1757
+ }
1758
+ }
1759
+ my ($index, $dirEnd, $numEntries);
1760
+ if ($dirStart + 4 < $dataLen) {
1761
+ $numEntries = Get16u($dataPt, $dirStart);
1762
+ $dirEnd = $dirStart + 2 + 12 * $numEntries;
1763
+ if ($dirEnd > $dataLen) {
1764
+ return ExifErr($exifTool, "Truncated $name directory", $tagTablePtr);
1765
+ }
1766
+ # sort entries if necessary (but not in maker notes IFDs)
1767
+ unless ($inMakerNotes) {
1768
+ my $lastID = -1;
1769
+ for ($index=0; $index<$numEntries; ++$index) {
1770
+ my $tagID = Get16u($dataPt, $dirStart + 2 + 12 * $index);
1771
+ # check for proper sequence (but ignore null entries at end)
1772
+ if ($tagID < $lastID and $tagID) {
1773
+ SortIFD($dataPt, $dirStart, $numEntries);
1774
+ $exifTool->Warn("Entries in $name were out of sequence. Fixed.",1);
1775
+ last;
1776
+ }
1777
+ $lastID = $tagID;
1778
+ }
1779
+ }
1780
+ } else {
1781
+ $numEntries = 0;
1782
+ $dirEnd = $dirStart;
1783
+ }
1784
+
1785
+ # loop through new values and accumulate all information for this IFD
1786
+ my (%set, %mayDelete, $tagInfo);
1787
+ my $wrongDir = $crossDelete{$dirName};
1788
+ foreach $tagInfo ($exifTool->GetNewTagInfoList($tagTablePtr)) {
1789
+ my $tagID = $$tagInfo{TagID};
1790
+ # evaluate conditional lists now if necessary
1791
+ if (ref $tagTablePtr->{$tagID} eq 'ARRAY' or $$tagInfo{Condition}) {
1792
+ my $curInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID);
1793
+ if (defined $curInfo and not $curInfo) {
1794
+ # need value to evaluate the condition
1795
+ my ($val) = $exifTool->GetNewValues($tagInfo);
1796
+ # must convert to binary for evaluating in Condition
1797
+ if ($$tagInfo{Format} and defined $val) {
1798
+ $val = WriteValue($val, $$tagInfo{Format}, $$tagInfo{Count});
1799
+ }
1800
+ if (defined $val) {
1801
+ my $fmt = $$tagInfo{Writable} || $$tagInfo{Format} || 'undef';
1802
+ my $cnt = $$tagInfo{Count} || 1;
1803
+ # always use old format/count for Condition in maker notes
1804
+ if ($inMakerNotes) {
1805
+ for ($index=0; $index<$numEntries; ++$index) {
1806
+ my $entry = $dirStart + 2 + 12 * $index;
1807
+ my $id = Get16u($dataPt, $entry);
1808
+ if ($id eq $tagID) {
1809
+ my $f = Get16u($dataPt, $entry + 2);
1810
+ if ($formatName[$f]) {
1811
+ $fmt = $formatName[$f];
1812
+ $cnt = Get32u($dataPt, $entry + 4);
1813
+ }
1814
+ last;
1815
+ }
1816
+ }
1817
+ }
1818
+ $curInfo = $exifTool->GetTagInfo($tagTablePtr, $tagID, \$val, $fmt, $cnt);
1819
+ } else {
1820
+ # may want to delete this, but we need to see the value first
1821
+ $mayDelete{$tagID} = 1;
1822
+ }
1823
+ }
1824
+ # don't set this tag unless valid for the current condition
1825
+ next unless defined $curInfo and $curInfo eq $tagInfo;
1826
+ }
1827
+ if ($$tagInfo{WriteCondition}) {
1828
+ my $self = $exifTool; # set $self to be used in eval
1829
+ #### eval WriteCondition ($self)
1830
+ unless (eval $$tagInfo{WriteCondition}) {
1831
+ $@ and warn $@;
1832
+ next;
1833
+ }
1834
+ }
1835
+ my $nvHash = $exifTool->GetNewValueHash($tagInfo, $dirName);
1836
+ unless ($nvHash) {
1837
+ next unless $wrongDir;
1838
+ # delete stuff from the wrong directory if setting somewhere else
1839
+ $nvHash = $exifTool->GetNewValueHash($tagInfo, $wrongDir);
1840
+ # don't cross delete if not overwriting
1841
+ next unless $exifTool->IsOverwriting($nvHash);
1842
+ # don't cross delete if specifically deleting from the other directory
1843
+ # (Note: don't call GetValue() here because it shouldn't be called
1844
+ # if IsOverwriting returns < 0 -- ie. when shifting)
1845
+ next if not defined $$nvHash{Value} and $nvHash->{WantGroup} and
1846
+ lc($nvHash->{WantGroup}) eq lc($wrongDir);
1847
+ # remove this tag if found in this IFD
1848
+ $xDelete{$tagID} = 1;
1849
+ }
1850
+ if ($set{$tagID}) {
1851
+ # this tag is being set twice, which can happen if two Condition's
1852
+ # were true for this tag. Hopefully the only case where this can
1853
+ # happen is the MakerNotes tag since it may store two very different
1854
+ # types of information (MakerNotes and PreviewImage), but we want
1855
+ # to store the MakerNotes if both are available
1856
+ if ($tagID == 0x927c and $dirName =~ /^(ExifIFD|IFD0)$/) {
1857
+ next if $$tagInfo{Name} eq 'PreviewImage';
1858
+ } else {
1859
+ $exifTool->Warn(sprintf("Multiple new values for $name tag 0x%.4x",$tagID));
1860
+ }
1861
+ }
1862
+ $set{$tagID} = $tagInfo;
1863
+ }
1864
+
1865
+ # fix base offsets (some cameras incorrectly write maker notes in IFD0)
1866
+ if ($dirName eq 'MakerNotes' and $$dirInfo{Parent} =~ /^(ExifIFD|IFD0)$/ and
1867
+ $$exifTool{TIFF_TYPE} !~ /^(ARW|SR2)$/ and not $$exifTool{LeicaTrailerPos} and
1868
+ Image::ExifTool::MakerNotes::FixBase($exifTool, $dirInfo))
1869
+ {
1870
+ # update local variables from fixed values
1871
+ $base = $$dirInfo{Base};
1872
+ $dataPos = $$dirInfo{DataPos};
1873
+ }
1874
+
1875
+ # initialize variables to handle mandatory tags
1876
+ my $mandatory = $mandatory{$dirName};
1877
+ my ($allMandatory, $addMandatory);
1878
+ if ($mandatory) {
1879
+ # use X/Y resolution values from JFIF if available
1880
+ if ($dirName eq 'IFD0' and defined $$exifTool{JFIFYResolution}) {
1881
+ my %ifd0Vals = %$mandatory;
1882
+ $ifd0Vals{0x011a} = $$exifTool{JFIFXResolution};
1883
+ $ifd0Vals{0x011b} = $$exifTool{JFIFYResolution};
1884
+ $ifd0Vals{0x0128} = $$exifTool{JFIFResolutionUnit} + 1;
1885
+ $mandatory = \%ifd0Vals;
1886
+ }
1887
+ $allMandatory = $addMandatory = 0; # initialize to zero
1888
+ # add mandatory tags if creating a new directory
1889
+ unless ($numEntries) {
1890
+ foreach (keys %$mandatory) {
1891
+ $set{$_} or $set{$_} = $$tagTablePtr{$_};
1892
+ }
1893
+ }
1894
+ } else {
1895
+ undef $deleteAll; # don't remove directory (no mandatory entries)
1896
+ }
1897
+ my ($addDirs, @newTags);
1898
+ if ($inMakerNotes) {
1899
+ $addDirs = { }; # can't currently add new directories in MakerNotes
1900
+ # allow non-permanent makernotes tags to be added
1901
+ # (note: we may get into trouble if there are too many of these
1902
+ # because we allow out-of-order tags in MakerNote IFD's but our
1903
+ # logic to add new tags relies on ordered entries)
1904
+ foreach (keys %set) {
1905
+ my $perm = $set{$_}{Permanent};
1906
+ push @newTags, $_ if defined $perm and not $perm;
1907
+ }
1908
+ @newTags = sort { $a <=> $b } @newTags if @newTags > 1;
1909
+ } else {
1910
+ # get a hash of directories we will be writing in this one
1911
+ $addDirs = $exifTool->GetAddDirHash($tagTablePtr, $dirName);
1912
+ # make a union of tags & dirs (can set whole dirs, like MakerNotes)
1913
+ my %allTags = ( %set, %$addDirs );
1914
+ # make sorted list of new tags to be added
1915
+ @newTags = sort { $a <=> $b } keys(%allTags);
1916
+ }
1917
+ my $dirBuff = ''; # buffer for directory data
1918
+ my $valBuff = ''; # buffer for value data
1919
+ my @valFixups; # list of fixups for offsets in valBuff
1920
+ # fixup for offsets in dirBuff
1921
+ my $dirFixup = new Image::ExifTool::Fixup;
1922
+ my $entryBasedFixup;
1923
+ my $lastTagID = -1;
1924
+ my ($oldInfo, $oldFormat, $oldFormName, $oldCount, $oldSize, $oldValue, $oldImageData);
1925
+ my ($readFormat, $readFormName, $readCount); # format for reading old value(s)
1926
+ my ($entry, $valueDataPt, $valueDataPos, $valueDataLen, $valuePtr, $valEnd);
1927
+ my ($offList, $offHash, $ignoreCount, $fixCount);
1928
+ my $oldID = -1;
1929
+ my $newID = -1;
1930
+
1931
+ # patch for Canon EOS 40D firmware 1.0.4 bug (incorrect directory counts)
1932
+ if ($inMakerNotes and $$exifTool{Model} eq 'Canon EOS 40D') {
1933
+ my $fmt = Get16u($dataPt, $dirStart + 2 + 12 * ($numEntries - 1) + 2);
1934
+ if ($fmt < 1 or $fmt > 13) {
1935
+ # adjust the number of directory entries
1936
+ --$numEntries;
1937
+ $dirEnd -= 12;
1938
+ $ignoreCount = 1;
1939
+ }
1940
+ }
1941
+ #..............................................................................
1942
+ # loop through entries in new directory
1943
+ #
1944
+ $index = 0;
1945
+ Entry: for (;;) {
1946
+
1947
+ if (defined $oldID and $oldID == $newID) {
1948
+ #
1949
+ # read next entry from existing directory
1950
+ #
1951
+ if ($index < $numEntries) {
1952
+ $entry = $dirStart + 2 + 12 * $index;
1953
+ $oldID = Get16u($dataPt, $entry);
1954
+ $readFormat = $oldFormat = Get16u($dataPt, $entry+2);
1955
+ $readCount = $oldCount = Get32u($dataPt, $entry+4);
1956
+ undef $oldImageData;
1957
+ if ($oldFormat < 1 or $oldFormat > 13) {
1958
+ my $msg = "Bad format ($oldFormat) for $name entry $index";
1959
+ # patch to preserve invalid directory entries in SubIFD3 of
1960
+ # various Kodak Z-series cameras (Z812, Z1085IS, Z1275)
1961
+ # and some Sony cameras such as the DSC-P10
1962
+ if ($dirName eq 'MakerNotes' and (($$exifTool{Make}=~/KODAK/i and
1963
+ $$dirInfo{Name} and $$dirInfo{Name} eq 'SubIFD3') or
1964
+ ($numEntries == 12 and $$exifTool{Make} eq 'SONY' and $index >= 8)))
1965
+ {
1966
+ $dirBuff .= substr($$dataPt, $entry, 12);
1967
+ ++$index;
1968
+ $newID = $oldID; # we wrote this
1969
+ $exifTool->Warn($msg, 1);
1970
+ next;
1971
+ }
1972
+ # don't write out null directory entry
1973
+ if ($oldFormat==0 and $index and $oldCount==0) {
1974
+ $ignoreCount = ($ignoreCount || 0) + 1;
1975
+ # must keep same directory size to avoid messing up our fixed offsets
1976
+ $dirBuff .= ("\0" x 12) if $$dirInfo{FixBase};
1977
+ ++$index;
1978
+ $newID = $oldID; # pretend we wrote this
1979
+ next;
1980
+ }
1981
+ return ExifErr($exifTool, $msg, $tagTablePtr);
1982
+ }
1983
+ $readFormName = $oldFormName = $formatName[$oldFormat];
1984
+ $valueDataPt = $dataPt;
1985
+ $valueDataPos = $dataPos;
1986
+ $valueDataLen = $dataLen;
1987
+ $valuePtr = $entry + 8;
1988
+ # try direct method first for speed
1989
+ $oldInfo = $$tagTablePtr{$oldID};
1990
+ if (ref $oldInfo ne 'HASH' or $$oldInfo{Condition}) {
1991
+ # must get unknown tags too
1992
+ # (necessary so we don't miss a tag we want to Drop)
1993
+ my $unk = $exifTool->Options(Unknown => 1);
1994
+ $oldInfo = $exifTool->GetTagInfo($tagTablePtr, $oldID);
1995
+ $exifTool->Options(Unknown => $unk);
1996
+ }
1997
+ # patch incorrect count in Kodak SubIFD3 tags
1998
+ if ($oldCount < 2 and $oldInfo and $$oldInfo{FixCount}) {
1999
+ $offList or ($offList, $offHash) = GetOffList($dataPt, $dirStart, $dataPos,
2000
+ $numEntries, $tagTablePtr);
2001
+ my $i = $$offHash{Get32u($dataPt, $valuePtr)};
2002
+ if (defined $i and $i < $#$offList) {
2003
+ $oldCount = int(($$offList[$i+1] - $$offList[$i]) / $formatSize[$oldFormat]);
2004
+ $fixCount = ($fixCount || 0) + 1 if $oldCount != $readCount;
2005
+ }
2006
+ }
2007
+ $oldSize = $oldCount * $formatSize[$oldFormat];
2008
+ my $readFromFile;
2009
+ if ($oldSize > 4) {
2010
+ $valuePtr = Get32u($dataPt, $valuePtr);
2011
+ # fix valuePtr if necessary
2012
+ if ($$dirInfo{FixOffsets}) {
2013
+ $valEnd or $valEnd = $dataPos + $dirStart + 2 + 12 * $numEntries + 4;
2014
+ my ($tagID, $size, $wFlag) = ($oldID, $oldSize, 1);
2015
+ #### eval FixOffsets ($valuePtr, $valEnd, $size, $tagID, $wFlag)
2016
+ eval $$dirInfo{FixOffsets};
2017
+ unless (defined $valuePtr) {
2018
+ unless ($$exifTool{DROP_TAGS}) {
2019
+ my $tagStr = $oldInfo ? $$oldInfo{Name} : sprintf("tag 0x%.4x",$oldID);
2020
+ return undef if $exifTool->Error("Bad $name offset for $tagStr", $inMakerNotes);
2021
+ }
2022
+ ++$index; $oldID = $newID; next; # drop this tag
2023
+ }
2024
+ }
2025
+ # offset shouldn't point into TIFF or IFD header
2026
+ my $suspect = ($valuePtr < 8);
2027
+ # convert offset to pointer in $$dataPt
2028
+ if ($$dirInfo{EntryBased} or (ref $$tagTablePtr{$oldID} eq 'HASH' and
2029
+ $tagTablePtr->{$oldID}{EntryBased}))
2030
+ {
2031
+ $valuePtr += $entry;
2032
+ } else {
2033
+ $valuePtr -= $dataPos;
2034
+ }
2035
+ # value shouldn't overlap our directory
2036
+ $suspect = 1 if $valuePtr < $dirEnd and $valuePtr+$oldSize > $dirStart;
2037
+ # get value by seeking in file if we are allowed
2038
+ if ($valuePtr < 0 or $valuePtr+$oldSize > $dataLen) {
2039
+ my ($pos, $tagStr, $invalidPreview, $tmpInfo);
2040
+ if ($oldInfo) {
2041
+ $tagStr = $$oldInfo{Name};
2042
+ } elsif (defined $oldInfo) {
2043
+ $tmpInfo = $exifTool->GetTagInfo($tagTablePtr, $oldID, \ '', $oldFormName, $oldCount);
2044
+ $tagStr = $$tmpInfo{Name} if $tmpInfo;
2045
+ }
2046
+ $tagStr or $tagStr = sprintf("tag 0x%.4x",$oldID);
2047
+ # allow PreviewImage to run outside EXIF segment in JPEG images
2048
+ if (not $raf) {
2049
+ if ($tagStr eq 'PreviewImage') {
2050
+ $raf = $exifTool->{RAF};
2051
+ if ($raf) {
2052
+ $pos = $raf->Tell();
2053
+ if ($oldInfo and $$oldInfo{ChangeBase}) {
2054
+ # adjust base offset for this tag only
2055
+ #### eval ChangeBase ($dirStart,$dataPos)
2056
+ my $newBase = eval $$oldInfo{ChangeBase};
2057
+ $valuePtr += $newBase;
2058
+ }
2059
+ } else {
2060
+ $invalidPreview = 1;
2061
+ }
2062
+ } elsif ($tagStr eq 'MakerNoteLeica6') {
2063
+ # save information about Leica makernote trailer
2064
+ $$exifTool{LeicaTrailer} = {
2065
+ TagInfo => $oldInfo || $tmpInfo,
2066
+ Offset => $base + $valuePtr + $dataPos,
2067
+ Size => $oldSize,
2068
+ Fixup => new Image::ExifTool::Fixup,
2069
+ },
2070
+ $invalidPreview = 2;
2071
+ # remove SubDirectory to prevent processing (for now)
2072
+ my %copy = %{$oldInfo || $tmpInfo};
2073
+ delete $copy{SubDirectory};
2074
+ delete $copy{MakerNotes};
2075
+ $oldInfo = \%copy;
2076
+ }
2077
+ }
2078
+ if ($oldSize > BINARY_DATA_LIMIT and $$origDirInfo{ImageData} and
2079
+ (not defined $oldInfo or ($oldInfo and not $$oldInfo{SubDirectory})))
2080
+ {
2081
+ # copy huge data blocks later instead of loading into memory
2082
+ $oldValue = ''; # dummy empty value
2083
+ # copy this value later unless writing a new value
2084
+ unless ($set{$oldID}) {
2085
+ my $pad = $oldSize & 0x01 ? 1 : 0;
2086
+ # save block information to copy later (set directory offset later)
2087
+ $oldImageData = [$base+$valuePtr+$dataPos, $oldSize, $pad];
2088
+ }
2089
+ } elsif ($raf) {
2090
+ my $success = ($raf->Seek($base+$valuePtr+$dataPos, 0) and
2091
+ $raf->Read($oldValue, $oldSize) == $oldSize);
2092
+ if (defined $pos) {
2093
+ $raf->Seek($pos, 0);
2094
+ undef $raf;
2095
+ # (sony A700 has 32-byte header on PreviewImage)
2096
+ unless ($success and $oldValue =~ /^(\xff\xd8\xff|(.|.{33})\xd8\xff\xdb)/s) {
2097
+ $invalidPreview = 1;
2098
+ $success = 1; # continue writing directory anyway
2099
+ }
2100
+ }
2101
+ unless ($success) {
2102
+ return undef if $exifTool->Error("Error reading value for $name entry $index", $inMakerNotes);
2103
+ ++$index; $oldID = $newID; next; # drop this tag
2104
+ }
2105
+ } elsif (not $invalidPreview) {
2106
+ return undef if $exifTool->Error("Bad $name offset for $tagStr", $inMakerNotes);
2107
+ ++$index; $oldID = $newID; next; # drop this tag
2108
+ }
2109
+ if ($invalidPreview) {
2110
+ # set value for invalid preview
2111
+ if ($exifTool->{FILE_TYPE} eq 'JPEG') {
2112
+ # define dummy value for preview (or Leica MakerNote) to write later
2113
+ # (value must be larger than 4 bytes to generate PREVIEW_INFO,
2114
+ # and an even number of bytes so it won't be padded)
2115
+ $oldValue = 'LOAD_PREVIEW';
2116
+ } else {
2117
+ $oldValue = 'none';
2118
+ $oldSize = length $oldValue;
2119
+ }
2120
+ $valuePtr = 0;
2121
+ } else {
2122
+ UpdateTiffEnd($exifTool, $base+$valuePtr+$dataPos+$oldSize);
2123
+ }
2124
+ # update pointers for value just read from file
2125
+ $valueDataPt = \$oldValue;
2126
+ $valueDataPos = $valuePtr + $dataPos;
2127
+ $valueDataLen = $oldSize;
2128
+ $valuePtr = 0;
2129
+ $readFromFile = 1;
2130
+ }
2131
+ if ($suspect) {
2132
+ my $tagStr = $oldInfo ? $$oldInfo{Name} : sprintf('tag 0x%.4x', $oldID);
2133
+ my $str = "Suspicious $name offset for $tagStr";
2134
+ if ($inMakerNotes) {
2135
+ $exifTool->Warn($str, 1);
2136
+ } else {
2137
+ return undef if $exifTool->Error($str, 1);
2138
+ }
2139
+ }
2140
+ }
2141
+ # read value if we haven't already
2142
+ $oldValue = substr($$valueDataPt, $valuePtr, $oldSize) unless $readFromFile;
2143
+ # get tagInfo using value if necessary
2144
+ if (defined $oldInfo and not $oldInfo) {
2145
+ my $unk = $exifTool->Options(Unknown => 1);
2146
+ $oldInfo = $exifTool->GetTagInfo($tagTablePtr, $oldID, \$oldValue, $oldFormName, $oldCount);
2147
+ $exifTool->Options(Unknown => $unk);
2148
+ # now that we have the value, we can resolve the Condition to finally
2149
+ # determine whether we want to delete this tag or not
2150
+ if ($mayDelete{$oldID} and $oldInfo and (not @newTags or $newTags[0] != $oldID)) {
2151
+ my $nvHash = $exifTool->GetNewValueHash($oldInfo, $dirName);
2152
+ if (not $nvHash and $wrongDir) {
2153
+ # delete from wrong directory if necessary
2154
+ $nvHash = $exifTool->GetNewValueHash($oldInfo, $wrongDir);
2155
+ $nvHash and $xDelete{$oldID} = 1;
2156
+ }
2157
+ if ($nvHash) {
2158
+ # we want to delete this tag after all, so insert it into our list
2159
+ $set{$oldID} = $oldInfo;
2160
+ unshift @newTags, $oldID;
2161
+ }
2162
+ }
2163
+ }
2164
+ # make sure we are handling the 'ifd' format properly
2165
+ if (($oldFormat == 13 or $oldFormat == 18) and
2166
+ (not $oldInfo or not $$oldInfo{SubIFD}))
2167
+ {
2168
+ my $str = sprintf('%s tag 0x%.4x IFD format not handled', $name, $oldID);
2169
+ $exifTool->Error($str, $inMakerNotes);
2170
+ }
2171
+ # override format we use to read the value if specified
2172
+ if ($oldInfo) {
2173
+ # check for tags which must be integers
2174
+ if (($$oldInfo{IsOffset} or $$oldInfo{SubIFD}) and
2175
+ not $intFormat{$oldFormName})
2176
+ {
2177
+ $exifTool->Error("Invalid format ($oldFormName) for $name $$oldInfo{Name}", $inMakerNotes);
2178
+ ++$index; $oldID = $newID; next; # drop this tag
2179
+ }
2180
+ if ($$oldInfo{Drop} and $$exifTool{DROP_TAGS} and
2181
+ ($$oldInfo{Drop} == 1 or $$oldInfo{Drop} < $oldSize))
2182
+ {
2183
+ ++$index; $oldID = $newID; next; # drop this tag
2184
+ }
2185
+ if ($$oldInfo{Format}) {
2186
+ $readFormName = $$oldInfo{Format};
2187
+ $readFormat = $formatNumber{$readFormName};
2188
+ unless ($readFormat) {
2189
+ # we aren't reading in a standard EXIF format, so rewrite in old format
2190
+ $readFormName = $oldFormName;
2191
+ $readFormat = $oldFormat;
2192
+ }
2193
+ # adjust number of items to read if format size changed
2194
+ $readCount = $oldSize / $formatSize[$readFormat];
2195
+ }
2196
+ }
2197
+ if ($oldID <= $lastTagID and not $inMakerNotes) {
2198
+ my $str = $oldInfo ? "$$oldInfo{Name} tag" : sprintf('tag 0x%x',$oldID);
2199
+ if ($oldID == $lastTagID) {
2200
+ $exifTool->Warn("Duplicate $str in $name");;
2201
+ } else {
2202
+ $exifTool->Warn("\u$str out of sequence in $name");
2203
+ }
2204
+ }
2205
+ $lastTagID = $oldID;
2206
+ ++$index; # increment index for next time
2207
+ } else {
2208
+ undef $oldID; # no more existing entries
2209
+ }
2210
+ }
2211
+ #
2212
+ # write out all new tags, up to and including this one
2213
+ #
2214
+ $newID = $newTags[0];
2215
+ my $isNew; # -1=tag is old, 0=tag same as existing, 1=tag is new
2216
+ if (not defined $oldID) {
2217
+ last unless defined $newID;
2218
+ $isNew = 1;
2219
+ } elsif (not defined $newID) {
2220
+ # maker notes will have no new tags defined
2221
+ if ($set{$oldID}) {
2222
+ $newID = $oldID;
2223
+ $isNew = 0;
2224
+ } else {
2225
+ $isNew = -1;
2226
+ }
2227
+ } else {
2228
+ $isNew = $oldID <=> $newID;
2229
+ }
2230
+ my $newInfo = $oldInfo;
2231
+ my $newFormat = $oldFormat;
2232
+ my $newFormName = $oldFormName;
2233
+ my $newCount = $oldCount;
2234
+ my $ifdFormName;
2235
+ my $newValue;
2236
+ my $newValuePt = $isNew >= 0 ? \$newValue : \$oldValue;
2237
+ my $isOverwriting;
2238
+
2239
+ if ($isNew >= 0) {
2240
+ # add, edit or delete this tag
2241
+ shift @newTags; # remove from list
2242
+ if ($set{$newID}) {
2243
+ #
2244
+ # set the new tag value (or 'next' if deleting tag)
2245
+ #
2246
+ $newInfo = $set{$newID};
2247
+ $newCount = $$newInfo{Count};
2248
+ my ($val, $newVal, $n);
2249
+ my $nvHash = $exifTool->GetNewValueHash($newInfo, $dirName);
2250
+ if ($isNew > 0) {
2251
+ # don't create new entry unless requested
2252
+ if ($nvHash) {
2253
+ next unless $$nvHash{IsCreating};
2254
+ if ($$newInfo{IsOverwriting}) {
2255
+ my $proc = $$newInfo{IsOverwriting};
2256
+ $isOverwriting = &$proc($exifTool, $nvHash, $val, \$newVal);
2257
+ } else {
2258
+ $isOverwriting = $exifTool->IsOverwriting($nvHash);
2259
+ }
2260
+ } else {
2261
+ next if $xDelete{$newID}; # don't create if cross deleting
2262
+ $newVal = $$mandatory{$newID}; # get value for mandatory tag
2263
+ $isOverwriting = 1;
2264
+ }
2265
+ # convert using new format
2266
+ if ($$newInfo{Format}) {
2267
+ $newFormName = $$newInfo{Format};
2268
+ # use Writable flag to specify IFD format code
2269
+ $ifdFormName = $$newInfo{Writable};
2270
+ } else {
2271
+ $newFormName = $$newInfo{Writable};
2272
+ unless ($newFormName) {
2273
+ warn("No format for $name $$newInfo{Name}\n");
2274
+ next;
2275
+ }
2276
+ }
2277
+ $newFormat = $formatNumber{$newFormName};
2278
+ } elsif ($nvHash or $xDelete{$newID}) {
2279
+ unless ($nvHash) {
2280
+ $nvHash = $exifTool->GetNewValueHash($newInfo, $wrongDir);
2281
+ }
2282
+ # read value
2283
+ if (length $oldValue >= $oldSize) {
2284
+ $val = ReadValue(\$oldValue, 0, $readFormName, $readCount, $oldSize);
2285
+ } else {
2286
+ $val = '';
2287
+ }
2288
+ # determine write format (by default, use 'Writable' format)
2289
+ my $writable = $$newInfo{Writable};
2290
+ # (or use existing format if 'Writable' not specified)
2291
+ $writable = $oldFormName unless $writable and $writable ne '1';
2292
+ # (and override write format with 'Format' if specified)
2293
+ my $writeForm = $$newInfo{Format} || $writable;
2294
+ if ($writeForm ne $newFormName) {
2295
+ # write in specified format
2296
+ $newFormName = $writeForm;
2297
+ $newFormat = $formatNumber{$newFormName};
2298
+ # use different IFD format code if necessary
2299
+ if ($inMakerNotes) {
2300
+ # always preserve IFD format in maker notes
2301
+ $ifdFormName = $oldFormName;
2302
+ } elsif ($writable ne $newFormName) {
2303
+ # use specified IFD format
2304
+ $ifdFormName = $writable;
2305
+ }
2306
+ }
2307
+ if ($inMakerNotes and $readFormName ne 'string' and $readFormName ne 'undef') {
2308
+ # keep same size in maker notes unless string or binary
2309
+ $newCount = $oldCount * $formatSize[$oldFormat] / $formatSize[$newFormat];
2310
+ }
2311
+ if ($$newInfo{IsOverwriting}) {
2312
+ my $proc = $$newInfo{IsOverwriting};
2313
+ $isOverwriting = &$proc($exifTool, $nvHash, $val, \$newVal);
2314
+ } else {
2315
+ $isOverwriting = $exifTool->IsOverwriting($nvHash, $val);
2316
+ }
2317
+ }
2318
+ if ($isOverwriting) {
2319
+ $newVal = $exifTool->GetNewValues($nvHash) unless defined $newVal;
2320
+ # value undefined if deleting this tag
2321
+ # (also delete tag if cross-deleting and this isn't a date/time shift)
2322
+ if (not defined $newVal or ($xDelete{$newID} and not defined $$nvHash{Shift})) {
2323
+ if ($$newInfo{RawConvInv} and defined $$nvHash{Value}) {
2324
+ # error in RawConvInv, so rewrite existing tag
2325
+ goto NoOverwrite; # GOTO!
2326
+ }
2327
+ unless ($isNew) {
2328
+ ++$exifTool->{CHANGED};
2329
+ $exifTool->VerboseValue("- $dirName:$$newInfo{Name}", $val);
2330
+ }
2331
+ next;
2332
+ }
2333
+ if ($newCount and $newCount < 0) {
2334
+ # set count to number of values if variable
2335
+ my @vals = split ' ',$newVal;
2336
+ $newCount = @vals;
2337
+ }
2338
+ # convert to binary format
2339
+ $newValue = WriteValue($newVal, $newFormName, $newCount);
2340
+ unless (defined $newValue) {
2341
+ $exifTool->Warn("Invalid value for $dirName:$$newInfo{Name}");
2342
+ goto NoOverwrite; # GOTO!
2343
+ }
2344
+ if (length $newValue) {
2345
+ # limit maximum value length in JPEG images
2346
+ # (max segment size is 65533 bytes and the min EXIF size is 96 incl an additional IFD entry)
2347
+ if ($$exifTool{FILE_TYPE} eq 'JPEG' and length($newValue) > 65436 and
2348
+ $$newInfo{Name} ne 'PreviewImage')
2349
+ {
2350
+ my $name = $$newInfo{MakerNotes} ? 'MakerNotes' : $$newInfo{Name};
2351
+ $exifTool->Warn("$name too large to write in JPEG segment");
2352
+ goto NoOverwrite; # GOTO!
2353
+ }
2354
+ # re-code if necessary
2355
+ if ($strEnc and $newFormName eq 'string') {
2356
+ $newValue = $exifTool->Encode($newValue, $strEnc);
2357
+ }
2358
+ } else {
2359
+ $exifTool->Warn("Can't write zero length $$newInfo{Name} in $tagTablePtr->{GROUPS}{1}");
2360
+ goto NoOverwrite; # GOTO!
2361
+ }
2362
+ if ($isNew >= 0) {
2363
+ $newCount = length($newValue) / $formatSize[$newFormat];
2364
+ ++$exifTool->{CHANGED};
2365
+ if (defined $allMandatory) {
2366
+ # not all mandatory if we are writing any tag specifically
2367
+ if ($nvHash) {
2368
+ undef $allMandatory;
2369
+ undef $deleteAll;
2370
+ } else {
2371
+ ++$addMandatory; # count mandatory tags that we added
2372
+ }
2373
+ }
2374
+ if ($verbose > 1) {
2375
+ $exifTool->VerboseValue("- $dirName:$$newInfo{Name}", $val) unless $isNew;
2376
+ my $str = $nvHash ? '' : ' (mandatory)';
2377
+ $exifTool->VerboseValue("+ $dirName:$$newInfo{Name}", $newVal, $str);
2378
+ }
2379
+ }
2380
+ } else {
2381
+ NoOverwrite: next if $isNew > 0;
2382
+ $isNew = -1; # rewrite existing tag
2383
+ }
2384
+ # set format for EXIF IFD if different than conversion format
2385
+ if ($ifdFormName) {
2386
+ $newFormName = $ifdFormName;
2387
+ $newFormat = $formatNumber{$newFormName};
2388
+ }
2389
+
2390
+ } elsif ($isNew > 0) {
2391
+ #
2392
+ # create new subdirectory
2393
+ #
2394
+ # newInfo may not be defined if we try to add a mandatory tag
2395
+ # to a directory that doesn't support it (ie. IFD1 in RW2 images)
2396
+ $newInfo = $$addDirs{$newID} or next;
2397
+ # make sure we don't try to generate a new MakerNotes directory
2398
+ # or a SubIFD
2399
+ next if $$newInfo{MakerNotes} or $$newInfo{Name} eq 'SubIFD';
2400
+ my $subTable;
2401
+ if ($newInfo->{SubDirectory}{TagTable}) {
2402
+ $subTable = Image::ExifTool::GetTagTable($newInfo->{SubDirectory}{TagTable});
2403
+ } else {
2404
+ $subTable = $tagTablePtr;
2405
+ }
2406
+ # create empty source directory
2407
+ my %sourceDir = (
2408
+ Parent => $dirName,
2409
+ Fixup => new Image::ExifTool::Fixup,
2410
+ );
2411
+ $sourceDir{DirName} = $newInfo->{Groups}{1} if $$newInfo{SubIFD};
2412
+ $newValue = $exifTool->WriteDirectory(\%sourceDir, $subTable);
2413
+ # only add new directory if it isn't empty
2414
+ next unless defined $newValue and length($newValue);
2415
+ # set the fixup start location
2416
+ if ($$newInfo{SubIFD}) {
2417
+ # subdirectory is referenced by an offset in value buffer
2418
+ my $subdir = $newValue;
2419
+ $newValue = Set32u(0xfeedf00d);
2420
+ push @subdirs, {
2421
+ DataPt => \$subdir,
2422
+ Table => $subTable,
2423
+ Fixup => $sourceDir{Fixup},
2424
+ Offset => length($dirBuff) + 8,
2425
+ Where => 'dirBuff',
2426
+ };
2427
+ $newFormName = 'int32u';
2428
+ $newFormat = $formatNumber{$newFormName};
2429
+ } else {
2430
+ # subdirectory goes directly into value buffer
2431
+ $sourceDir{Fixup}{Start} += length($valBuff);
2432
+ # use Writable to set format, otherwise 'undef'
2433
+ $newFormName = $$newInfo{Writable};
2434
+ unless ($newFormName and $formatNumber{$newFormName}) {
2435
+ $newFormName = 'undef';
2436
+ }
2437
+ $newFormat = $formatNumber{$newFormName};
2438
+ push @valFixups, $sourceDir{Fixup};
2439
+ }
2440
+ } elsif ($$newInfo{Format} and $$newInfo{Writable} and $$newInfo{Writable} ne '1') {
2441
+ # use specified write format
2442
+ $newFormName = $$newInfo{Writable};
2443
+ $newFormat = $formatNumber{$newFormName};
2444
+ } elsif ($$addDirs{$newID} and $newInfo ne $$addDirs{$newID}) {
2445
+ # this can happen if we are trying to add a directory that doesn't exist
2446
+ # in this type of file (ie. try adding a SubIFD tag to an A100 image)
2447
+ $isNew = -1;
2448
+ }
2449
+ }
2450
+ if ($isNew < 0) {
2451
+ # just rewrite existing tag
2452
+ $newID = $oldID;
2453
+ $newValue = $oldValue;
2454
+ $newFormat = $oldFormat; # (just in case it changed)
2455
+ $newFormName = $oldFormName;
2456
+ # set offset of this entry in the directory so we can update the pointer
2457
+ # and save block information to copy this large block later
2458
+ if ($oldImageData) {
2459
+ $$oldImageData[3] = $newStart + length($dirBuff) + 2;
2460
+ push @imageData, $oldImageData;
2461
+ $$origDirInfo{ImageData} = \@imageData;
2462
+ }
2463
+ }
2464
+ if ($newInfo) {
2465
+ #
2466
+ # load necessary data for this tag (thumbnail image, etc)
2467
+ #
2468
+ if ($$newInfo{DataTag} and $isNew >= 0) {
2469
+ my $dataTag = $$newInfo{DataTag};
2470
+ # load data for this tag
2471
+ unless (defined $offsetData{$dataTag} or $dataTag eq 'LeicaTrailer') {
2472
+ # prefer tag from Composite table if it exists (otherwise
2473
+ # PreviewImage data would be taken from Extra tag)
2474
+ my $compInfo = $Image::ExifTool::Composite{$dataTag};
2475
+ $offsetData{$dataTag} = $exifTool->GetNewValues($compInfo || $dataTag);
2476
+ my $err;
2477
+ if (defined $offsetData{$dataTag}) {
2478
+ my $len = length $offsetData{$dataTag};
2479
+ if ($dataTag eq 'PreviewImage') {
2480
+ # must set DEL_PREVIEW flag now if preview fit into IFD
2481
+ $$exifTool{DEL_PREVIEW} = 1 if $len <= 4;
2482
+ } elsif ($exifTool->{FILE_TYPE} eq 'JPEG' and $len > 60000) {
2483
+ delete $offsetData{$dataTag};
2484
+ $err = "$dataTag not written (too large for JPEG segment)";
2485
+ }
2486
+ } else {
2487
+ $err = "$dataTag not found";
2488
+ }
2489
+ if ($err) {
2490
+ $exifTool->Warn($err) if $$newInfo{IsOffset};
2491
+ delete $set{$newID}; # remove from list of tags we are setting
2492
+ next;
2493
+ }
2494
+ }
2495
+ }
2496
+ #
2497
+ # write maker notes
2498
+ #
2499
+ if ($$newInfo{MakerNotes}) {
2500
+ # don't write new makernotes if we are deleting this group
2501
+ if ($exifTool->{DEL_GROUP}{MakerNotes} and
2502
+ ($exifTool->{DEL_GROUP}{MakerNotes} != 2 or $isNew <= 0))
2503
+ {
2504
+ if ($isNew <= 0) {
2505
+ ++$exifTool->{CHANGED};
2506
+ $verbose and print $out " Deleting MakerNotes\n";
2507
+ }
2508
+ next;
2509
+ }
2510
+ my $saveOrder = GetByteOrder();
2511
+ if ($isNew >= 0 and $set{$newID}) {
2512
+ # we are writing a whole new maker note block
2513
+ # --> add fixup information if necessary
2514
+ my $nvHash = $exifTool->GetNewValueHash($newInfo, $dirName);
2515
+ if ($nvHash and $nvHash->{MAKER_NOTE_FIXUP}) {
2516
+ # must clone fixup because we will be shifting it
2517
+ my $makerFixup = $nvHash->{MAKER_NOTE_FIXUP}->Clone();
2518
+ my $valLen = length($valBuff);
2519
+ $makerFixup->{Start} += $valLen;
2520
+ push @valFixups, $makerFixup;
2521
+ }
2522
+ } else {
2523
+ # update maker notes if possible
2524
+ my %subdirInfo = (
2525
+ Base => $base,
2526
+ DataPt => $valueDataPt,
2527
+ DataPos => $valueDataPos,
2528
+ DataLen => $valueDataLen,
2529
+ DirStart => $valuePtr,
2530
+ DirLen => $oldSize,
2531
+ DirName => 'MakerNotes',
2532
+ Name => $$newInfo{Name},
2533
+ Parent => $dirName,
2534
+ TagInfo => $newInfo,
2535
+ RAF => $raf,
2536
+ );
2537
+ my ($subTable, $subdir, $loc, $writeProc, $notIFD);
2538
+ if ($$newInfo{SubDirectory}) {
2539
+ my $sub = $$newInfo{SubDirectory};
2540
+ $subdirInfo{FixBase} = 1 if $$sub{FixBase};
2541
+ $subdirInfo{FixOffsets} = $$sub{FixOffsets};
2542
+ $subdirInfo{EntryBased} = $$sub{EntryBased};
2543
+ $subdirInfo{NoFixBase} = 1 if defined $$sub{Base};
2544
+ $subdirInfo{AutoFix} = $$sub{AutoFix};
2545
+ }
2546
+ # get the proper tag table for these maker notes
2547
+ if ($oldInfo and $$oldInfo{SubDirectory}) {
2548
+ $subTable = $$oldInfo{SubDirectory}{TagTable};
2549
+ $subTable and $subTable = Image::ExifTool::GetTagTable($subTable);
2550
+ $writeProc = $$oldInfo{SubDirectory}{WriteProc};
2551
+ $notIFD = $$oldInfo{NotIFD};
2552
+ } else {
2553
+ $exifTool->Warn('Internal problem getting maker notes tag table');
2554
+ }
2555
+ $subTable or $subTable = $tagTablePtr;
2556
+ if ($writeProc and
2557
+ $writeProc eq \&Image::ExifTool::MakerNotes::WriteUnknownOrPreview and
2558
+ $oldValue =~ /^\xff\xd8\xff/)
2559
+ {
2560
+ $loc = 0;
2561
+ } elsif (not $notIFD) {
2562
+ # look for IFD-style maker notes
2563
+ $loc = Image::ExifTool::MakerNotes::LocateIFD($exifTool,\%subdirInfo);
2564
+ }
2565
+ if (defined $loc) {
2566
+ # we need fixup data for this subdirectory
2567
+ $subdirInfo{Fixup} = new Image::ExifTool::Fixup;
2568
+ # rewrite maker notes
2569
+ my $changed = $$exifTool{CHANGED};
2570
+ $subdir = $exifTool->WriteDirectory(\%subdirInfo, $subTable, $writeProc);
2571
+ if ($changed == $$exifTool{CHANGED} and $subdirInfo{Fixup}->IsEmpty()) {
2572
+ # return original data if nothing changed and no fixups
2573
+ undef $subdir;
2574
+ }
2575
+ } elsif ($$subTable{PROCESS_PROC} and
2576
+ $$subTable{PROCESS_PROC} eq \&Image::ExifTool::ProcessBinaryData)
2577
+ {
2578
+ my $sub = $$oldInfo{SubDirectory};
2579
+ if (defined $$sub{Start}) {
2580
+ #### eval Start ($valuePtr)
2581
+ my $start = eval $$sub{Start};
2582
+ $loc = $start - $valuePtr;
2583
+ $subdirInfo{DirStart} = $start;
2584
+ $subdirInfo{DirLen} -= $loc;
2585
+ } else {
2586
+ $loc = 0;
2587
+ }
2588
+ # rewrite maker notes
2589
+ $subdir = $exifTool->WriteDirectory(\%subdirInfo, $subTable);
2590
+ } elsif (not $notIFD) {
2591
+ my $msg = 'Maker notes could not be parsed';
2592
+ if ($$exifTool{FILE_TYPE} eq 'JPEG') {
2593
+ $exifTool->Warn($msg, 1);
2594
+ } else {
2595
+ $exifTool->Error($msg, 1);
2596
+ }
2597
+ }
2598
+ if (defined $subdir) {
2599
+ next unless length $subdir;
2600
+ my $valLen = length($valBuff);
2601
+ # restore existing header and substitute the new
2602
+ # maker notes for the old value
2603
+ $newValue = substr($oldValue, 0, $loc) . $subdir;
2604
+ my $makerFixup = $subdirInfo{Fixup};
2605
+ my $previewInfo = $exifTool->{PREVIEW_INFO};
2606
+ if ($subdirInfo{Relative}) {
2607
+ # apply a one-time fixup to $loc since offsets are relative
2608
+ $makerFixup->{Start} += $loc;
2609
+ # shift all offsets to be relative to new base
2610
+ my $baseShift = $valueDataPos + $valuePtr + $base - $subdirInfo{Base};
2611
+ $makerFixup->{Shift} += $baseShift;
2612
+ $makerFixup->ApplyFixup(\$newValue);
2613
+ if ($previewInfo) {
2614
+ # remove all but PreviewImage fixup (since others shouldn't change)
2615
+ foreach (keys %{$makerFixup->{Pointers}}) {
2616
+ /_PreviewImage$/ or delete $makerFixup->{Pointers}{$_};
2617
+ }
2618
+ # zero pointer so we can see how it gets shifted later
2619
+ $makerFixup->SetMarkerPointers(\$newValue, 'PreviewImage', 0);
2620
+ # set the pointer to the start of the EXIF information
2621
+ # add preview image fixup to list of value fixups
2622
+ $makerFixup->{Start} += $valLen;
2623
+ push @valFixups, $makerFixup;
2624
+ $previewInfo->{BaseShift} = $baseShift;
2625
+ $previewInfo->{Relative} = 1;
2626
+ }
2627
+ # don't shift anything if relative flag set to zero (Pentax patch)
2628
+ } elsif (not defined $subdirInfo{Relative}) {
2629
+ # shift offset base if shifted in the original image or if FixBase
2630
+ # was used, but be careful of automatic FixBase with negative shifts
2631
+ # since they may lead to negative (invalid) offsets (casio_edit_problem.jpg)
2632
+ my $baseShift = $base - $subdirInfo{Base};
2633
+ if ($subdirInfo{AutoFix}) {
2634
+ $baseShift = 0;
2635
+ } elsif ($subdirInfo{FixBase} and $baseShift < 0 and
2636
+ # allow negative base shift if offsets are bigger (PentaxOptioWP.jpg)
2637
+ (not $subdirInfo{MinOffset} or $subdirInfo{MinOffset} + $baseShift < 0))
2638
+ {
2639
+ my $fixBase = $exifTool->Options('FixBase');
2640
+ if (not defined $fixBase) {
2641
+ my $str = $exifTool->Options('IgnoreMinorErrors') ? 'ignored' : 'fix or ignore?';
2642
+ $exifTool->Error("MakerNotes offsets may be incorrect ($str)", 1);
2643
+ } elsif ($fixBase eq '') {
2644
+ $exifTool->Warn('Fixed incorrect MakerNotes offsets');
2645
+ $baseShift = 0;
2646
+ }
2647
+ }
2648
+ $makerFixup->{Start} += $valLen + $loc;
2649
+ $makerFixup->{Shift} += $baseShift;
2650
+ # permanently fix makernote offset errors
2651
+ $makerFixup->{Shift} += $subdirInfo{FixedBy} || 0;
2652
+ push @valFixups, $makerFixup;
2653
+ if ($previewInfo and not $previewInfo->{NoBaseShift}) {
2654
+ $previewInfo->{BaseShift} = $baseShift;
2655
+ }
2656
+ }
2657
+ $newValuePt = \$newValue; # write new value
2658
+ }
2659
+ }
2660
+ SetByteOrder($saveOrder);
2661
+
2662
+ # process existing subdirectory unless we are overwriting it entirely
2663
+ } elsif ($$newInfo{SubDirectory} and $isNew <= 0 and not $isOverwriting
2664
+ # don't edit directory if Writable is set to 0
2665
+ and (not defined $$newInfo{Writable} or $$newInfo{Writable}))
2666
+ {
2667
+
2668
+ my $subdir = $$newInfo{SubDirectory};
2669
+ if ($$newInfo{SubIFD}) {
2670
+ #
2671
+ # rewrite existing sub IFD's
2672
+ #
2673
+ my $subTable = $tagTablePtr;
2674
+ if ($$subdir{TagTable}) {
2675
+ $subTable = Image::ExifTool::GetTagTable($$subdir{TagTable});
2676
+ }
2677
+ # determine directory name for this IFD
2678
+ my $subdirName = $newInfo->{Groups}{1} || $$newInfo{Name};
2679
+ # all makernotes directory names must be 'MakerNotes'
2680
+ $subdirName = 'MakerNotes' if $subTable->{GROUPS}{0} eq 'MakerNotes';
2681
+ # must handle sub-IFD's specially since the values
2682
+ # are actually offsets to subdirectories
2683
+ unless ($readCount) { # can't have zero count
2684
+ return undef if $exifTool->Error("$name entry $index has zero count", 2);
2685
+ next;
2686
+ }
2687
+ my $writeCount = 0;
2688
+ my $i;
2689
+ $newValue = ''; # reset value because we regenerate it below
2690
+ for ($i=0; $i<$readCount; ++$i) {
2691
+ my $off = $i * $formatSize[$readFormat];
2692
+ my $pt = ReadValue($valueDataPt, $valuePtr + $off,
2693
+ $readFormName, 1, $oldSize - $off);
2694
+ my $subdirStart = $pt - $dataPos;
2695
+ my $subdirBase = $base;
2696
+ if ($$subdir{Base}) {
2697
+ my $start = $subdirStart + $dataPos;
2698
+ #### eval Base ($start,$base)
2699
+ $subdirBase += eval $$subdir{Base};
2700
+ }
2701
+ # add IFD number if more than one
2702
+ $subdirName =~ s/\d*$/$i/ if $i;
2703
+ my %subdirInfo = (
2704
+ Base => $subdirBase,
2705
+ DataPt => $dataPt,
2706
+ DataPos => $dataPos - $subdirBase + $base,
2707
+ DataLen => $dataLen,
2708
+ DirStart => $subdirStart,
2709
+ DirName => $subdirName,
2710
+ Name => $$newInfo{Name},
2711
+ TagInfo => $newInfo,
2712
+ Parent => $dirName,
2713
+ Fixup => new Image::ExifTool::Fixup,
2714
+ RAF => $raf,
2715
+ Subdir => $subdir,
2716
+ # set ImageData only for 1st level SubIFD's
2717
+ ImageData=> $imageDataFlag eq 'Main' ? 'SubIFD' : undef,
2718
+ );
2719
+ # pass on header pointer only for certain sub IFD's
2720
+ $subdirInfo{HeaderPtr} = $$dirInfo{HeaderPtr} if $$newInfo{SubIFD} == 2;
2721
+ if ($$subdir{RelativeBase}) {
2722
+ # apply one-time fixup if offsets are relative (Sony IDC hack)
2723
+ delete $subdirInfo{Fixup};
2724
+ delete $subdirInfo{ImageData};
2725
+ }
2726
+ # is the subdirectory outside our current data?
2727
+ if ($subdirStart < 0 or $subdirStart + 2 > $dataLen) {
2728
+ if ($raf) {
2729
+ # reset SubDirectory buffer (we will load it later)
2730
+ my $buff = '';
2731
+ $subdirInfo{DataPt} = \$buff;
2732
+ $subdirInfo{DataLen} = 0;
2733
+ } else {
2734
+ my @err = ("Can't read $subdirName data", $inMakerNotes);
2735
+ if ($$subTable{VARS} and $subTable->{VARS}{MINOR_ERRORS}) {
2736
+ $exifTool->Warn($err[0] . '. Ignored.');
2737
+ } elsif ($exifTool->Error(@err)) {
2738
+ return undef;
2739
+ }
2740
+ next Entry; # don't write this directory
2741
+ }
2742
+ }
2743
+ my $subdirData = $exifTool->WriteDirectory(\%subdirInfo, $subTable, $$subdir{WriteProc});
2744
+ unless (defined $subdirData) {
2745
+ # WriteDirectory should have issued an error, but check just in case
2746
+ $exifTool->Error("Error writing $subdirName") unless $$exifTool{VALUE}{Error};
2747
+ return undef;
2748
+ }
2749
+ unless (length $subdirData) {
2750
+ next unless $inMakerNotes;
2751
+ # don't delete MakerNote Sub-IFD's, write empty IFD instead
2752
+ $subdirData = "\0" x 6;
2753
+ # reset SubIFD ImageData and Fixup just to be safe
2754
+ delete $subdirInfo{ImageData};
2755
+ delete $subdirInfo{Fixup};
2756
+ }
2757
+ # handle data blocks that we will transfer later
2758
+ if (ref $subdirInfo{ImageData}) {
2759
+ push @imageData, @{$subdirInfo{ImageData}};
2760
+ $$origDirInfo{ImageData} = \@imageData;
2761
+ }
2762
+ # temporarily set value to subdirectory index
2763
+ # (will set to actual offset later when we know what it is)
2764
+ $newValue .= Set32u(0xfeedf00d);
2765
+ my ($offset, $where);
2766
+ if ($readCount > 1) {
2767
+ $offset = length($valBuff) + $i * 4;
2768
+ $where = 'valBuff';
2769
+ } else {
2770
+ $offset = length($dirBuff) + 8;
2771
+ $where = 'dirBuff';
2772
+ }
2773
+ # add to list of subdirectories we will append later
2774
+ push @subdirs, {
2775
+ DataPt => \$subdirData,
2776
+ Table => $subTable,
2777
+ Fixup => $subdirInfo{Fixup},
2778
+ Offset => $offset,
2779
+ Where => $where,
2780
+ ImageData => $subdirInfo{ImageData},
2781
+ };
2782
+ ++$writeCount; # count number of subdirs written
2783
+ }
2784
+ next unless length $newValue;
2785
+ # must change location of subdir offset if we deleted
2786
+ # a directory and only one remains
2787
+ if ($writeCount < $readCount and $writeCount == 1) {
2788
+ $subdirs[-1]{Where} = 'dirBuff';
2789
+ $subdirs[-1]{Offset} = length($dirBuff) + 8;
2790
+ }
2791
+ # set new format to int32u for IFD
2792
+ $newFormName = $$newInfo{FixFormat} || 'int32u';
2793
+ $newFormat = $formatNumber{$newFormName};
2794
+ $newValuePt = \$newValue;
2795
+
2796
+ } elsif ((not defined $$subdir{Start} or
2797
+ $$subdir{Start} =~ /\$valuePtr/) and
2798
+ $$subdir{TagTable})
2799
+ {
2800
+ #
2801
+ # rewrite other existing subdirectories ('$valuePtr' type only)
2802
+ #
2803
+ # set subdirectory Start and Base
2804
+ my $subdirStart = $valuePtr;
2805
+ if ($$subdir{Start}) {
2806
+ #### eval Start ($valuePtr)
2807
+ $subdirStart = eval $$subdir{Start};
2808
+ # must adjust directory size if start changed
2809
+ $oldSize -= $subdirStart - $valuePtr;
2810
+ }
2811
+ my $subdirBase = $base;
2812
+ if ($$subdir{Base}) {
2813
+ my $start = $subdirStart + $valueDataPos;
2814
+ #### eval Base ($start,$base)
2815
+ $subdirBase += eval $$subdir{Base};
2816
+ }
2817
+ my $subFixup = new Image::ExifTool::Fixup;
2818
+ my %subdirInfo = (
2819
+ Base => $subdirBase,
2820
+ DataPt => $valueDataPt,
2821
+ DataPos => $valueDataPos - $subdirBase + $base,
2822
+ DataLen => $valueDataLen,
2823
+ DirStart => $subdirStart,
2824
+ DirName => $$subdir{DirName},
2825
+ DirLen => $oldSize,
2826
+ Parent => $dirName,
2827
+ Fixup => $subFixup,
2828
+ RAF => $raf,
2829
+ TagInfo => $newInfo,
2830
+ );
2831
+ unless ($oldSize) {
2832
+ # replace with dummy data if empty to prevent WriteDirectory
2833
+ # routines from accessing data they shouldn't
2834
+ my $tmp = '';
2835
+ $subdirInfo{DataPt} = \$tmp;
2836
+ $subdirInfo{DataLen} = 0;
2837
+ $subdirInfo{DirStart} = 0;
2838
+ $subdirInfo{DataPos} += $subdirStart;
2839
+ }
2840
+ my $subTable = Image::ExifTool::GetTagTable($$subdir{TagTable});
2841
+ my $oldOrder = GetByteOrder();
2842
+ SetByteOrder($$subdir{ByteOrder}) if $$subdir{ByteOrder};
2843
+ $newValue = $exifTool->WriteDirectory(\%subdirInfo, $subTable, $$subdir{WriteProc});
2844
+ SetByteOrder($oldOrder);
2845
+ if (defined $newValue) {
2846
+ my $hdrLen = $subdirStart - $valuePtr;
2847
+ if ($hdrLen) {
2848
+ $newValue = substr($$valueDataPt, $valuePtr, $hdrLen) . $newValue;
2849
+ $subFixup->{Start} += $hdrLen;
2850
+ }
2851
+ $newValuePt = \$newValue;
2852
+ } else {
2853
+ $newValuePt = \$oldValue;
2854
+ }
2855
+ unless (length $$newValuePt) {
2856
+ # don't delete a previously empty makernote directory
2857
+ next if $oldSize or not $inMakerNotes;
2858
+ }
2859
+ if ($subFixup->{Pointers} and $subdirInfo{Base} == $base) {
2860
+ $subFixup->{Start} += length $valBuff;
2861
+ push @valFixups, $subFixup;
2862
+ } else {
2863
+ # apply fixup in case we added a header ($hdrLen above)
2864
+ $subFixup->ApplyFixup(\$newValue);
2865
+ }
2866
+ }
2867
+
2868
+ } elsif ($$newInfo{OffsetPair}) {
2869
+ #
2870
+ # keep track of offsets
2871
+ #
2872
+ my $dataTag = $$newInfo{DataTag} || '';
2873
+ if ($dataTag eq 'CanonVRD') {
2874
+ # must decide now if we will write CanonVRD information
2875
+ my $hasVRD;
2876
+ if ($exifTool->{NEW_VALUE}{$Image::ExifTool::Extra{CanonVRD}}) {
2877
+ # adding or deleting as a block
2878
+ $hasVRD = $exifTool->GetNewValues('CanonVRD') ? 1 : 0;
2879
+ } elsif ($exifTool->{DEL_GROUP}{CanonVRD} or
2880
+ $exifTool->{DEL_GROUP}{Trailer})
2881
+ {
2882
+ $hasVRD = 0; # deleting as a group
2883
+ } else {
2884
+ $hasVRD = ($$newValuePt ne "\0\0\0\0");
2885
+ }
2886
+ if ($hasVRD) {
2887
+ # add a fixup, and set this offset later
2888
+ $dirFixup->AddFixup(length($dirBuff) + 8, $dataTag);
2889
+ } else {
2890
+ # there is (or will soon be) no VRD information, so set pointer to zero
2891
+ $newValue = "\0" x length($$newValuePt);
2892
+ $newValuePt = \$newValue;
2893
+ }
2894
+ } elsif ($dataTag eq 'OriginalDecisionData') {
2895
+ # handle Canon OriginalDecisionData (no associated length tag)
2896
+ # - I'm going out of my way here to preserve data which is
2897
+ # invalidated anyway by our edits
2898
+ my $odd;
2899
+ my $oddInfo = $Image::ExifTool::Composite{OriginalDecisionData};
2900
+ if ($oddInfo and $exifTool->{NEW_VALUE}{$oddInfo}) {
2901
+ $odd = $exifTool->GetNewValues($dataTag);
2902
+ if ($verbose > 1) {
2903
+ print $out " - $dirName:$dataTag\n" if $$newValuePt ne "\0\0\0\0";
2904
+ print $out " + $dirName:$dataTag\n" if $odd;
2905
+ }
2906
+ ++$exifTool->{CHANGED};
2907
+ } elsif ($$newValuePt ne "\0\0\0\0") {
2908
+ if (length($$newValuePt) == 4) {
2909
+ require Image::ExifTool::Canon;
2910
+ my $offset = Get32u($newValuePt,0);
2911
+ # absolute offset in JPEG images only
2912
+ $offset += $base unless $$exifTool{FILE_TYPE} eq 'JPEG';
2913
+ $odd = Image::ExifTool::Canon::ReadODD($exifTool, $offset);
2914
+ $odd = $$odd if ref $odd;
2915
+ } else {
2916
+ $exifTool->Error("Invalid $$newInfo{Name}",1);
2917
+ }
2918
+ }
2919
+ if ($odd) {
2920
+ my $newOffset = length($valBuff);
2921
+ # (ODD offset is absolute in JPEG, so add base offset!)
2922
+ $newOffset += $base if $$exifTool{FILE_TYPE} eq 'JPEG';
2923
+ $newValue = Set32u($newOffset);
2924
+ $dirFixup->AddFixup(length($dirBuff) + 8, $dataTag);
2925
+ $valBuff .= $odd; # add original decision data
2926
+ } else {
2927
+ $newValue = "\0\0\0\0";
2928
+ }
2929
+ $newValuePt = \$newValue;
2930
+ } else {
2931
+ my $offsetInfo = $offsetInfo[$ifd];
2932
+ # save original values (for updating TIFF_END later)
2933
+ my @vals;
2934
+ if ($isNew <= 0) {
2935
+ my $oldOrder = GetByteOrder();
2936
+ # Minolta A200 stores these in the wrong byte order!
2937
+ SetByteOrder($$newInfo{ByteOrder}) if $$newInfo{ByteOrder};
2938
+ @vals = ReadValue(\$oldValue, 0, $readFormName, $readCount, $oldSize);
2939
+ SetByteOrder($oldOrder);
2940
+ }
2941
+ # only support int32 pointers (for now)
2942
+ if ($formatSize[$newFormat] != 4 and $$newInfo{IsOffset}) {
2943
+ $isNew > 0 and warn("Internal error (Offset not int32)"), return undef;
2944
+ $newCount != $readCount and warn("Wrong count!"), return undef;
2945
+ # change to int32
2946
+ $newFormName = 'int32u';
2947
+ $newFormat = $formatNumber{$newFormName};
2948
+ $newValue = WriteValue(join(' ',@vals), $newFormName, $newCount);
2949
+ unless (defined $newValue) {
2950
+ warn "Internal error writing offsets for $$newInfo{Name}\n";
2951
+ return undef;
2952
+ }
2953
+ }
2954
+ $offsetInfo or $offsetInfo = $offsetInfo[$ifd] = { };
2955
+ # save location of valuePtr in new directory
2956
+ # (notice we add 10 instead of 8 for valuePtr because
2957
+ # we will put a 2-byte count at start of directory later)
2958
+ my $ptr = $newStart + length($dirBuff) + 10;
2959
+ $newCount or $newCount = 1; # make sure count is set for offsetInfo
2960
+ # save value pointer and value count for each tag
2961
+ $offsetInfo->{$newID} = [$newInfo, $ptr, $newCount, \@vals, $newFormat];
2962
+ }
2963
+
2964
+ } elsif ($$newInfo{DataMember}) {
2965
+
2966
+ # save any necessary data members (Make, Model, etc)
2967
+ my $formatStr = $newFormName;
2968
+ my $count = $newCount;
2969
+ # change to specified format if necessary
2970
+ if ($$newInfo{Format} and $$newInfo{Format} ne $formatStr) {
2971
+ $formatStr = $$newInfo{Format};
2972
+ my $format = $formatNumber{$formatStr};
2973
+ # adjust number of items for new format size
2974
+ $count = int(length($$newValuePt) / $formatSize[$format]) if $format;
2975
+ }
2976
+ my $val = ReadValue($newValuePt,0,$formatStr,$count,length($$newValuePt));
2977
+ my $conv = $$newInfo{RawConv};
2978
+ if ($conv) {
2979
+ # let the RawConv store the (possibly converted) data member
2980
+ if (ref $conv eq 'CODE') {
2981
+ &$conv($val, $exifTool);
2982
+ } else {
2983
+ my ($self, $tag, $taginfo) = ($exifTool, $$newInfo{Name}, $newInfo);
2984
+ #### eval RawConv ($self, $val, $tag, $tagInfo)
2985
+ eval $conv;
2986
+ }
2987
+ } else {
2988
+ $$exifTool{$$newInfo{DataMember}} = $val;
2989
+ }
2990
+ }
2991
+ }
2992
+ #
2993
+ # write out the directory entry
2994
+ #
2995
+ my $newSize = length($$newValuePt);
2996
+ my $fsize = $formatSize[$newFormat];
2997
+ my $offsetVal;
2998
+ $newCount = int(($newSize + $fsize - 1) / $fsize); # set proper count
2999
+ if ($newSize > 4) {
3000
+ # zero-pad to an even number of bytes (required by EXIF standard)
3001
+ # and make sure we are a multiple of the format size
3002
+ while ($newSize & 0x01 or $newSize < $newCount * $fsize) {
3003
+ $$newValuePt .= "\0";
3004
+ ++$newSize;
3005
+ }
3006
+ my $entryBased;
3007
+ if ($$dirInfo{EntryBased} or ($newInfo and $$newInfo{EntryBased})) {
3008
+ $entryBased = 1;
3009
+ $offsetVal = Set32u(length($valBuff) - length($dirBuff));
3010
+ } else {
3011
+ $offsetVal = Set32u(length $valBuff);
3012
+ }
3013
+ my ($dataTag, $putFirst);
3014
+ ($dataTag, $putFirst) = @$newInfo{'DataTag','PutFirst'} if $newInfo;
3015
+ if ($dataTag) {
3016
+ if ($dataTag eq 'PreviewImage' and ($exifTool->{FILE_TYPE} eq 'JPEG' or
3017
+ $$exifTool{GENERATE_PREVIEW_INFO}))
3018
+ {
3019
+ # hold onto the PreviewImage until we can determine if it fits
3020
+ $exifTool->{PREVIEW_INFO} or $exifTool->{PREVIEW_INFO} = {
3021
+ Data => $$newValuePt,
3022
+ Fixup => new Image::ExifTool::Fixup,
3023
+ };
3024
+ $exifTool->{PREVIEW_INFO}{ChangeBase} = 1 if $$newInfo{ChangeBase};
3025
+ if ($$newInfo{IsOffset} and $$newInfo{IsOffset} eq '2') {
3026
+ $exifTool->{PREVIEW_INFO}{NoBaseShift} = 1;
3027
+ }
3028
+ # use original preview size if we will attempt to load it later
3029
+ $newCount = $oldCount if $$newValuePt eq 'LOAD_PREVIEW';
3030
+ $$newValuePt = '';
3031
+ } elsif ($dataTag eq 'LeicaTrailer' and $$exifTool{LeicaTrailer}) {
3032
+ $$newValuePt = '';
3033
+ }
3034
+ }
3035
+ if ($putFirst and $$dirInfo{HeaderPtr}) {
3036
+ my $hdrPtr = $$dirInfo{HeaderPtr};
3037
+ # place this value immediately after the TIFF header
3038
+ $offsetVal = Set32u(length $$hdrPtr);
3039
+ $$hdrPtr .= $$newValuePt;
3040
+ } else {
3041
+ $valBuff .= $$newValuePt; # add value data to buffer
3042
+ # must save a fixup pointer for every pointer in the directory
3043
+ if ($entryBased) {
3044
+ $entryBasedFixup or $entryBasedFixup = new Image::ExifTool::Fixup;
3045
+ $entryBasedFixup->AddFixup(length($dirBuff) + 8, $dataTag);
3046
+ } else {
3047
+ $dirFixup->AddFixup(length($dirBuff) + 8, $dataTag);
3048
+ }
3049
+ }
3050
+ } else {
3051
+ $offsetVal = $$newValuePt; # save value in offset if 4 bytes or less
3052
+ # must pad value with zeros if less than 4 bytes
3053
+ $newSize < 4 and $offsetVal .= "\0" x (4 - $newSize);
3054
+ }
3055
+ # write the directory entry
3056
+ $dirBuff .= Set16u($newID) . Set16u($newFormat) .
3057
+ Set32u($newCount) . $offsetVal;
3058
+ # update flag to keep track of mandatory tags
3059
+ while (defined $allMandatory) {
3060
+ if (defined $$mandatory{$newID}) {
3061
+ # values must correspond to mandatory values
3062
+ my $form = $$newInfo{Format} || $newFormName;
3063
+ my $mandVal = WriteValue($$mandatory{$newID}, $form, $newCount);
3064
+ if (defined $mandVal and $mandVal eq $$newValuePt) {
3065
+ ++$allMandatory; # count mandatory tags
3066
+ last;
3067
+ }
3068
+ }
3069
+ undef $deleteAll;
3070
+ undef $allMandatory;
3071
+ }
3072
+ }
3073
+ if ($ignoreCount) {
3074
+ my $y = $ignoreCount > 1 ? 'ies' : 'y';
3075
+ my $verb = $$dirInfo{FixBase} ? 'Ignored' : 'Removed';
3076
+ $exifTool->Warn("$verb $ignoreCount invalid entr$y from $name", 1);
3077
+ }
3078
+ if ($fixCount) {
3079
+ my $s = $fixCount > 1 ? 's' : '';
3080
+ $exifTool->Warn("Fixed invalid count$s for $fixCount $name tag$s", 1);
3081
+ }
3082
+ #..............................................................................
3083
+ # write directory counts and nextIFD pointer and add value data to end of IFD
3084
+ #
3085
+ # determine now if there is or will be another IFD after this one
3086
+ my $nextIfdOffset;
3087
+ if ($dirEnd + 4 <= $dataLen) {
3088
+ $nextIfdOffset = Get32u($dataPt, $dirEnd);
3089
+ } else {
3090
+ $nextIfdOffset = 0;
3091
+ }
3092
+ my $isNextIFD = ($$dirInfo{Multi} and ($nextIfdOffset or
3093
+ # account for the case where we will create the next IFD
3094
+ # (IFD1 only, but not in TIFF-format images)
3095
+ ($dirName eq 'IFD0' and $$exifTool{ADD_DIRS}{'IFD1'} and
3096
+ $$exifTool{FILE_TYPE} ne 'TIFF')));
3097
+ # calculate number of entries in new directory
3098
+ my $newEntries = length($dirBuff) / 12;
3099
+ # delete entire directory if we deleted a tag and only mandatory tags remain or we
3100
+ # attempted to create a directory with only mandatory tags and there is no nextIFD
3101
+ if ($allMandatory and not $isNextIFD and ($newEntries < $numEntries or $numEntries == 0)) {
3102
+ $newEntries = 0;
3103
+ $dirBuff = '';
3104
+ $valBuff = '';
3105
+ undef $dirFixup; # no fixups in this directory
3106
+ ++$deleteAll if defined $deleteAll;
3107
+ $verbose > 1 and print $out " - $allMandatory mandatory tag(s)\n";
3108
+ $exifTool->{CHANGED} -= $addMandatory; # didn't change these after all
3109
+ }
3110
+ if ($ifd and not $newEntries) {
3111
+ $verbose and print $out " Deleting IFD1\n";
3112
+ last; # don't write IFD1 if empty
3113
+ }
3114
+ # apply one-time fixup for entry-based offsets
3115
+ if ($entryBasedFixup) {
3116
+ $entryBasedFixup->{Shift} = length($dirBuff) + 4;
3117
+ $entryBasedFixup->ApplyFixup(\$dirBuff);
3118
+ undef $entryBasedFixup;
3119
+ }
3120
+ # add directory entry count to start of IFD and next IFD pointer to end
3121
+ # (temporarily set next IFD pointer to zero)
3122
+ $newData .= Set16u($newEntries) . $dirBuff . Set32u(0);
3123
+ # get position of value data in newData
3124
+ my $valPos = length($newData);
3125
+ # go back now and set next IFD pointer if this isn't the first IFD
3126
+ if ($nextIfdPos) {
3127
+ # set offset to next IFD
3128
+ Set32u($newStart, \$newData, $nextIfdPos);
3129
+ $fixup->AddFixup($nextIfdPos,'NextIFD'); # add fixup for this offset in newData
3130
+ }
3131
+ # remember position of 'next IFD' pointer so we can set it next time around
3132
+ $nextIfdPos = $valPos - 4;
3133
+ # add value data after IFD
3134
+ $newData .= $valBuff;
3135
+ #
3136
+ # add any subdirectories, adding fixup information
3137
+ #
3138
+ if (@subdirs) {
3139
+ my $subdir;
3140
+ foreach $subdir (@subdirs) {
3141
+ my $len = length($newData); # position of subdirectory in data
3142
+ my $subdirFixup = $$subdir{Fixup};
3143
+ if ($subdirFixup) {
3144
+ $$subdirFixup{Start} += $len;
3145
+ $fixup->AddFixup($subdirFixup);
3146
+ }
3147
+ my $imageData = $$subdir{ImageData};
3148
+ my $blockSize = 0;
3149
+ # must also update start position for ImageData fixups
3150
+ if (ref $imageData) {
3151
+ my $blockInfo;
3152
+ foreach $blockInfo (@$imageData) {
3153
+ my ($pos, $size, $pad, $entry, $subFix) = @$blockInfo;
3154
+ if ($subFix) {
3155
+ $$subFix{Start} += $len;
3156
+ # save expected image data offset for calculating shift later
3157
+ $$subFix{BlockLen} = length(${$$subdir{DataPt}}) + $blockSize;
3158
+ }
3159
+ $blockSize += $size + $pad;
3160
+ }
3161
+ }
3162
+ $newData .= ${$$subdir{DataPt}}; # add subdirectory to our data
3163
+ undef ${$$subdir{DataPt}}; # free memory now
3164
+ # set the pointer
3165
+ my $offset = $$subdir{Offset};
3166
+ # if offset is in valBuff, it was added to the end of dirBuff
3167
+ # (plus 4 bytes for nextIFD pointer)
3168
+ $offset += length($dirBuff) + 4 if $$subdir{Where} eq 'valBuff';
3169
+ $offset += $newStart + 2; # get offset in newData
3170
+ # check to be sure we got the right offset
3171
+ unless (Get32u(\$newData, $offset) == 0xfeedf00d) {
3172
+ $exifTool->Error("Internal error while rewriting $name");
3173
+ return undef;
3174
+ }
3175
+ # set the offset to the subdirectory data
3176
+ Set32u($len, \$newData, $offset);
3177
+ $fixup->AddFixup($offset); # add fixup for this offset in newData
3178
+ }
3179
+ }
3180
+ # add fixup for all offsets in directory according to value data position
3181
+ # (which is at the end of this directory)
3182
+ if ($dirFixup) {
3183
+ $dirFixup->{Start} = $newStart + 2;
3184
+ $dirFixup->{Shift} = $valPos - $dirFixup->{Start};
3185
+ $fixup->AddFixup($dirFixup);
3186
+ }
3187
+ # add valueData fixups, adjusting for position of value data
3188
+ my $valFixup;
3189
+ foreach $valFixup (@valFixups) {
3190
+ $valFixup->{Start} += $valPos;
3191
+ $fixup->AddFixup($valFixup);
3192
+ }
3193
+ # stop if no next IFD pointer
3194
+ last unless $isNextIFD; # stop unless scanning for multiple IFD's
3195
+ if ($nextIfdOffset) {
3196
+ # continue with next IFD
3197
+ $dirStart = $nextIfdOffset - $dataPos;
3198
+ } else {
3199
+ # create IFD1 if necessary
3200
+ $verbose and print $out " Creating IFD1\n";
3201
+ my $ifd1 = "\0" x 2; # empty IFD1 data (zero entry count)
3202
+ $dataPt = \$ifd1;
3203
+ $dirStart = 0;
3204
+ $dirLen = $dataLen = 2;
3205
+ }
3206
+ # increment IFD name
3207
+ my $ifdNum = $dirName =~ s/(\d+)$// ? $1 : 0;
3208
+ $dirName .= $ifdNum + 1;
3209
+ $name =~ s/\d+$//;
3210
+ $name .= $ifdNum + 1;
3211
+ $$exifTool{DIR_NAME} = $$exifTool{PATH}[-1] = $dirName;
3212
+ next unless $nextIfdOffset;
3213
+
3214
+ # guard against writing the same directory twice
3215
+ my $addr = $nextIfdOffset + $base;
3216
+ if ($exifTool->{PROCESSED}{$addr}) {
3217
+ $exifTool->Error("$name pointer references previous $exifTool->{PROCESSED}{$addr} directory", 1);
3218
+ last;
3219
+ }
3220
+ $exifTool->{PROCESSED}{$addr} = $name;
3221
+
3222
+ if ($dirName eq 'SubIFD1' and not ValidateIFD($dirInfo, $dirStart)) {
3223
+ if ($exifTool->{TIFF_TYPE} eq 'TIFF') {
3224
+ $exifTool->Error('Ignored bad IFD linked from SubIFD', 1);
3225
+ } elsif ($verbose) {
3226
+ $exifTool->Warn('Ignored bad IFD linked from SubIFD');
3227
+ }
3228
+ last; # don't write bad IFD
3229
+ }
3230
+ if ($exifTool->{DEL_GROUP}{$dirName}) {
3231
+ $verbose and print $out " Deleting $dirName\n";
3232
+ $raf and $exifTool->Error("Deleting $dirName also deletes subsequent" .
3233
+ " IFD's and possibly image data", 1);
3234
+ ++$exifTool->{CHANGED};
3235
+ if ($exifTool->{DEL_GROUP}{$dirName} == 2 and
3236
+ $exifTool->{ADD_DIRS}{$dirName})
3237
+ {
3238
+ my $emptyIFD = "\0" x 2; # start with empty IFD
3239
+ $dataPt = \$emptyIFD;
3240
+ $dirStart = 0;
3241
+ $dirLen = $dataLen = 2;
3242
+ } else {
3243
+ last; # don't write this IFD (or any subsequent IFD)
3244
+ }
3245
+ } else {
3246
+ $verbose and print $out " Rewriting $name\n";
3247
+ }
3248
+ }
3249
+ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3250
+
3251
+ # do our fixups now so we can more easily calculate offsets below
3252
+ $fixup->ApplyFixup(\$newData);
3253
+ #
3254
+ # determine total block size for deferred data
3255
+ #
3256
+ my $numBlocks = scalar @imageData; # save this so we scan only existing blocks later
3257
+ my $blockSize = 0; # total size of blocks to copy later
3258
+ my $blockInfo;
3259
+ foreach $blockInfo (@imageData) {
3260
+ my ($pos, $size, $pad) = @$blockInfo;
3261
+ $blockSize += $size + $pad;
3262
+ }
3263
+ #
3264
+ # copy over image data for IFD's, starting with the last IFD first
3265
+ #
3266
+ if (@offsetInfo) {
3267
+ my $ttwLen; # length of MRW TTW segment
3268
+ my @writeLater; # write image data last
3269
+ for ($ifd=$#offsetInfo; $ifd>=-1; --$ifd) {
3270
+ # build list of offsets to process
3271
+ my @offsetList;
3272
+ if ($ifd >= 0) {
3273
+ my $offsetInfo = $offsetInfo[$ifd] or next;
3274
+ # patch Panasonic RAW/RW2 StripOffsets/StripByteCounts if necessary
3275
+ my $stripOffsets = $$offsetInfo{0x111};
3276
+ if ($stripOffsets and $$stripOffsets[0]{PanasonicHack}) {
3277
+ require Image::ExifTool::PanasonicRaw;
3278
+ my $err = Image::ExifTool::PanasonicRaw::PatchRawDataOffset($offsetInfo, $raf, $ifd);
3279
+ $err and $exifTool->Error($err);
3280
+ }
3281
+ my $tagID;
3282
+ # loop through all tags in reverse order so we save thumbnail
3283
+ # data before main image data if both exist in the same IFD
3284
+ foreach $tagID (reverse sort keys %$offsetInfo) {
3285
+ my $tagInfo = $offsetInfo->{$tagID}[0];
3286
+ next unless $$tagInfo{IsOffset}; # handle byte counts with offsets
3287
+ my $sizeInfo = $offsetInfo->{$$tagInfo{OffsetPair}};
3288
+ $sizeInfo or $exifTool->Error("No size tag for $dirName:$$tagInfo{Name}"), next;
3289
+ my $dataTag = $$tagInfo{DataTag};
3290
+ # write TIFF image data (strips or tiles) later if requested
3291
+ if ($raf and defined $$origDirInfo{ImageData} and
3292
+ ($tagID == 0x111 or $tagID == 0x144 or
3293
+ # also defer writing of other big data such as JpgFromRaw in NEF
3294
+ ($$sizeInfo[3][0] and
3295
+ # (calculate approximate combined size of all blocks)
3296
+ $$sizeInfo[3][0] * scalar(@{$$sizeInfo[3]}) > 1000000)) and
3297
+ # but don't defer writing if replacing with new value
3298
+ (not defined $dataTag or not defined $offsetData{$dataTag}))
3299
+ {
3300
+ push @writeLater, [ $offsetInfo->{$tagID}, $sizeInfo ];
3301
+ } else {
3302
+ push @offsetList, [ $offsetInfo->{$tagID}, $sizeInfo ];
3303
+ }
3304
+ }
3305
+ } else {
3306
+ last unless @writeLater;
3307
+ @offsetList = @writeLater;
3308
+ }
3309
+ my $offsetPair;
3310
+ foreach $offsetPair (@offsetList) {
3311
+ my ($tagInfo, $offsets, $count, $oldOffset) = @{$$offsetPair[0]};
3312
+ my ($cntInfo, $byteCounts, $count2, $oldSize, $format) = @{$$offsetPair[1]};
3313
+ # must be the same number of offset and byte count values
3314
+ unless ($count == $count2) {
3315
+ $exifTool->Error("Offsets/ByteCounts disagree on count for $$tagInfo{Name}");
3316
+ return undef;
3317
+ }
3318
+ my $formatStr = $formatName[$format];
3319
+ # follow pointer to value data if necessary
3320
+ $count > 1 and $offsets = Get32u(\$newData, $offsets);
3321
+ my $n = $count * $formatSize[$format];
3322
+ $n > 4 and $byteCounts = Get32u(\$newData, $byteCounts);
3323
+ if ($byteCounts < 0 or $byteCounts + $n > length($newData)) {
3324
+ $exifTool->Error("Error reading $$tagInfo{Name} byte counts");
3325
+ return undef;
3326
+ }
3327
+ # get offset base and data pos (abnormal for some preview images)
3328
+ my ($dbase, $dpos, $wrongBase, $subIfdDataFixup);
3329
+ if ($$tagInfo{IsOffset} eq '2') {
3330
+ $dbase = $firstBase;
3331
+ $dpos = $dataPos + $base - $firstBase;
3332
+ } else {
3333
+ $dbase = $base;
3334
+ $dpos = $dataPos;
3335
+ }
3336
+ # use different base if necessary for some offsets (Minolta A200)
3337
+ if ($$tagInfo{WrongBase}) {
3338
+ my $self = $exifTool;
3339
+ #### eval WrongBase ($self)
3340
+ $wrongBase = eval $$tagInfo{WrongBase} || 0;
3341
+ $dbase += $wrongBase;
3342
+ $dpos -= $wrongBase;
3343
+ } else {
3344
+ $wrongBase = 0;
3345
+ }
3346
+ my $oldOrder = GetByteOrder();
3347
+ my $dataTag = $$tagInfo{DataTag};
3348
+ # use different byte order for values of this offset pair if required (Minolta A200)
3349
+ SetByteOrder($$tagInfo{ByteOrder}) if $$tagInfo{ByteOrder};
3350
+ # transfer the data referenced by all offsets of this tag
3351
+ for ($n=0; $n<$count; ++$n) {
3352
+ my ($oldEnd, $size);
3353
+ if (@$oldOffset and @$oldSize) {
3354
+ # calculate end offset of this block
3355
+ $oldEnd = $$oldOffset[$n] + $$oldSize[$n];
3356
+ # update TIFF_END as if we read this data from file
3357
+ UpdateTiffEnd($exifTool, $oldEnd + $dbase);
3358
+ }
3359
+ my $offsetPos = $offsets + $n * 4;
3360
+ my $byteCountPos = $byteCounts + $n * $formatSize[$format];
3361
+ if ($$tagInfo{PanasonicHack}) {
3362
+ # use actual raw data length (may be different than StripByteCounts!)
3363
+ $size = $$oldSize[$n];
3364
+ } else {
3365
+ # use size of new data
3366
+ $size = ReadValue(\$newData, $byteCountPos, $formatStr, 1, 4);
3367
+ }
3368
+ my $offset = $$oldOffset[$n];
3369
+ if (defined $offset) {
3370
+ $offset -= $dpos;
3371
+ } elsif ($size != 0xfeedfeed) {
3372
+ $exifTool->Error('Internal error (no offset)');
3373
+ return undef;
3374
+ }
3375
+ my $newOffset = length($newData) - $wrongBase;
3376
+ my $buff;
3377
+ # look for 'feed' code to use our new data
3378
+ if ($size == 0xfeedfeed) {
3379
+ unless (defined $dataTag) {
3380
+ $exifTool->Error("No DataTag defined for $$tagInfo{Name}");
3381
+ return undef;
3382
+ }
3383
+ unless (defined $offsetData{$dataTag}) {
3384
+ $exifTool->Error("Internal error (no $dataTag)");
3385
+ return undef;
3386
+ }
3387
+ if ($count > 1) {
3388
+ $exifTool->Error("Can't modify $$tagInfo{Name} with count $count");
3389
+ return undef;
3390
+ }
3391
+ $buff = $offsetData{$dataTag};
3392
+ if ($formatSize[$format] != 4) {
3393
+ $exifTool->Error("$$cntInfo{Name} is not int32");
3394
+ return undef;
3395
+ }
3396
+ # set the data size
3397
+ $size = length($buff);
3398
+ Set32u($size, \$newData, $byteCountPos);
3399
+ } elsif ($ifd < 0) {
3400
+ # pad if necessary (but don't pad contiguous image blocks)
3401
+ my $pad = 0;
3402
+ ++$pad if $size & 0x01 and ($n+1 >= $count or not $oldEnd or
3403
+ $oldEnd != $$oldOffset[$n+1]);
3404
+ # preserve original image padding if specified
3405
+ if ($$origDirInfo{PreserveImagePadding} and $n+1 < $count and
3406
+ $oldEnd and $$oldOffset[$n+1] > $oldEnd)
3407
+ {
3408
+ $pad = $$oldOffset[$n+1] - $oldEnd;
3409
+ }
3410
+ # copy data later
3411
+ push @imageData, [$offset+$dbase+$dpos, $size, $pad];
3412
+ $newOffset += $blockSize; # data comes after other deferred data
3413
+ # create fixup for SubIFD ImageData
3414
+ if ($imageDataFlag eq 'SubIFD' and not $subIfdDataFixup) {
3415
+ $subIfdDataFixup = new Image::ExifTool::Fixup;
3416
+ $imageData[-1][4] = $subIfdDataFixup;
3417
+ }
3418
+ $size += $pad; # account for pad byte if necessary
3419
+ # return ImageData list
3420
+ $$origDirInfo{ImageData} = \@imageData;
3421
+ } elsif ($offset >= 0 and $offset+$size <= $dataLen) {
3422
+ # take data from old dir data buffer
3423
+ $buff = substr($$dataPt, $offset, $size);
3424
+ } elsif ($$exifTool{TIFF_TYPE} eq 'MRW') {
3425
+ # TTW segment must be an even 4 bytes long, so pad now if necessary
3426
+ my $n = length $newData;
3427
+ $buff = ($n & 0x03) ? "\0" x (4 - ($n & 0x03)) : '';
3428
+ $size = length($buff);
3429
+ # data exists after MRW TTW segment
3430
+ $ttwLen = length($newData) + $size unless defined $ttwLen;
3431
+ $newOffset = $offset + $dpos + $ttwLen - $dataLen;
3432
+ } elsif ($raf and $raf->Seek($offset+$dbase+$dpos,0) and
3433
+ $raf->Read($buff,$size) == $size)
3434
+ {
3435
+ # (data was read OK)
3436
+ # patch incorrect ThumbnailOffset in Sony A100 1.00 ARW images
3437
+ if ($$exifTool{TIFF_TYPE} eq 'ARW' and $$tagInfo{Name} eq 'ThumbnailOffset' and
3438
+ $$exifTool{Model} eq 'DSLR-A100' and $buff !~ /^\xff\xd8\xff/)
3439
+ {
3440
+ my $pos = $offset + $dbase + $dpos;
3441
+ my $try;
3442
+ if ($pos < 0x10000 and $raf->Seek($pos+0x10000,0) and
3443
+ $raf->Read($try,$size) == $size and $try =~ /^\xff\xd8\xff/)
3444
+ {
3445
+ $buff = $try;
3446
+ $exifTool->Warn('Adjusted incorrect A100 ThumbnailOffset', 1);
3447
+ } else {
3448
+ $exifTool->Error('Invalid ThumbnailImage');
3449
+ }
3450
+ }
3451
+ } elsif ($$tagInfo{Name} eq 'ThumbnailOffset' and $offset>=0 and $offset<$dataLen) {
3452
+ # Grrr. The Canon 350D writes the thumbnail with an incorrect byte count
3453
+ my $diff = $offset + $size - $dataLen;
3454
+ $exifTool->Warn("ThumbnailImage runs outside EXIF data by $diff bytes (truncated)",1);
3455
+ # set the size to the available data
3456
+ $size -= $diff;
3457
+ unless (WriteValue($size, $formatStr, 1, \$newData, $byteCountPos)) {
3458
+ warn 'Internal error writing thumbnail size';
3459
+ }
3460
+ # get the truncated image
3461
+ $buff = substr($$dataPt, $offset, $size);
3462
+ } elsif ($$tagInfo{Name} eq 'PreviewImageStart' and $exifTool->{FILE_TYPE} eq 'JPEG') {
3463
+ # try to load the preview image using the specified offset
3464
+ undef $buff;
3465
+ my $r = $exifTool->{RAF};
3466
+ if ($r and not $raf) {
3467
+ my $tell = $r->Tell();
3468
+ # read and validate
3469
+ undef $buff unless $r->Seek($offset+$base+$dataPos,0) and
3470
+ $r->Read($buff,$size) == $size and
3471
+ $buff =~ /^.\xd8\xff[\xc4\xdb\xe0-\xef]/s;
3472
+ $r->Seek($tell, 0) or $exifTool->Error('Seek error'), return undef;
3473
+ }
3474
+ # set flag if we must load PreviewImage
3475
+ $buff = 'LOAD_PREVIEW' unless defined $buff;
3476
+ } else {
3477
+ my $dataName = $dataTag || $$tagInfo{Name};
3478
+ return undef if $exifTool->Error("Error reading $dataName data in $name", $inMakerNotes);
3479
+ $buff = '';
3480
+ }
3481
+ if ($$tagInfo{Name} eq 'PreviewImageStart') {
3482
+ if ($$exifTool{FILE_TYPE} eq 'JPEG' and not $$tagInfo{MakerPreview}) {
3483
+ # hold onto the PreviewImage until we can determine if it fits
3484
+ $exifTool->{PREVIEW_INFO} or $exifTool->{PREVIEW_INFO} = {
3485
+ Data => $buff,
3486
+ Fixup => new Image::ExifTool::Fixup,
3487
+ };
3488
+ if ($$tagInfo{IsOffset} and $$tagInfo{IsOffset} eq '2') {
3489
+ $exifTool->{PREVIEW_INFO}{NoBaseShift} = 1;
3490
+ }
3491
+ if ($offset >= 0 and $offset+$size <= $dataLen) {
3492
+ # set flag indicating this preview wasn't in a trailer
3493
+ $exifTool->{PREVIEW_INFO}{WasContained} = 1;
3494
+ }
3495
+ $buff = '';
3496
+ } elsif ($$exifTool{TIFF_TYPE} eq 'ARW' and $$exifTool{Model} eq 'DSLR-A100') {
3497
+ # the A100 double-references the same preview, so ignore the
3498
+ # second one (the offset and size will be patched later)
3499
+ next if $$exifTool{A100PreviewLength};
3500
+ $$exifTool{A100PreviewLength} = length $buff if defined $buff;
3501
+ }
3502
+ }
3503
+ # update offset accordingly and add to end of new data
3504
+ Set32u($newOffset, \$newData, $offsetPos);
3505
+ # add a pointer to fix up this offset value (marked with DataTag name)
3506
+ $fixup->AddFixup($offsetPos, $dataTag);
3507
+ # also add to subIfdDataFixup if necessary
3508
+ $subIfdDataFixup->AddFixup($offsetPos, $dataTag) if $subIfdDataFixup;
3509
+ # must also (sometimes) update StripOffsets in Panasonic RW2 images
3510
+ my $otherPos = $$offsetPair[0][5];
3511
+ if ($otherPos and $$tagInfo{PanasonicHack}) {
3512
+ Set32u($newOffset, \$newData, $otherPos);
3513
+ $fixup->AddFixup($otherPos, $dataTag);
3514
+ }
3515
+ if ($ifd >= 0) {
3516
+ # buff length must be even (Note: may have changed since $size was set)
3517
+ $buff .= "\0" if length($buff) & 0x01;
3518
+ $newData .= $buff; # add this strip to the data
3519
+ } else {
3520
+ $blockSize += $size; # keep track of total size
3521
+ }
3522
+ }
3523
+ SetByteOrder($oldOrder);
3524
+ }
3525
+ }
3526
+ # verify that nothing else got written after determining TTW length
3527
+ if (defined $ttwLen and $ttwLen != length($newData)) {
3528
+ $exifTool->Error('Internal error writing MRW TTW');
3529
+ }
3530
+ }
3531
+ #
3532
+ # set offsets and generate fixups for tag values which were too large for memory
3533
+ #
3534
+ $blockSize = 0;
3535
+ foreach $blockInfo (@imageData) {
3536
+ my ($pos, $size, $pad, $entry, $subFix) = @$blockInfo;
3537
+ if (defined $entry) {
3538
+ my $format = Get16u(\$newData, $entry + 2);
3539
+ if ($format < 1 or $format > 13) {
3540
+ $exifTool->Error('Internal error copying huge value');
3541
+ last;
3542
+ } else {
3543
+ # set count and offset in directory entry
3544
+ Set32u($size / $formatSize[$format], \$newData, $entry + 4);
3545
+ Set32u(length($newData)+$blockSize, \$newData, $entry + 8);
3546
+ $fixup->AddFixup($entry + 8);
3547
+ # create special fixup for SubIFD data
3548
+ if ($imageDataFlag eq 'SubIFD') {
3549
+ my $subIfdDataFixup = new Image::ExifTool::Fixup;
3550
+ $subIfdDataFixup->AddFixup($entry + 8);
3551
+ # save fixup in imageData list
3552
+ $$blockInfo[4] = $subIfdDataFixup;
3553
+ }
3554
+ # must reset entry pointer so we don't use it again in a parent IFD!
3555
+ $$blockInfo[3] = undef;
3556
+ }
3557
+ }
3558
+ # apply additional shift required for contained SubIFD image data offsets
3559
+ if ($subFix and defined $$subFix{BlockLen} and $numBlocks > 0) {
3560
+ # our offset expects the data at the end of the SubIFD block (BlockLen + Start),
3561
+ # but it will actually be at length($newData) + $blockSize. So adjust
3562
+ # accordingly (and subtract an extra Start because this shift is applied later)
3563
+ $subFix->{Shift} += length($newData) - $$subFix{BlockLen} - 2 * $$subFix{Start} + $blockSize;
3564
+ $subFix->ApplyFixup(\$newData);
3565
+ }
3566
+ $blockSize += $size + $pad;
3567
+ --$numBlocks;
3568
+ }
3569
+ #
3570
+ # apply final shift to new data position if this is the top level IFD
3571
+ #
3572
+ unless ($$dirInfo{Fixup}) {
3573
+ my $hdrPtr = $$dirInfo{HeaderPtr};
3574
+ my $newDataPos = $hdrPtr ? length $$hdrPtr : $$dirInfo{NewDataPos} || 0;
3575
+ # adjust CanonVRD offset to point to end of regular TIFF if necessary
3576
+ # (NOTE: This will be incorrect if multiple trailers exist,
3577
+ # but it is unlikely that it could ever be correct in this case anyway.
3578
+ # Also, this doesn't work for JPEG images (but CanonDPP doesn't set
3579
+ # this when editing JPEG images anyway))
3580
+ $fixup->SetMarkerPointers(\$newData, 'CanonVRD', length($newData) + $blockSize);
3581
+ if ($newDataPos) {
3582
+ $fixup->{Shift} += $newDataPos;
3583
+ $fixup->ApplyFixup(\$newData);
3584
+ }
3585
+ # save fixup for adjusting Leica trailer offset if necessary
3586
+ $$exifTool{LeicaTrailer}{Fixup}->AddFixup($fixup) if $$exifTool{LeicaTrailer};
3587
+ # save fixup for PreviewImage in JPEG file if necessary
3588
+ my $previewInfo = $exifTool->{PREVIEW_INFO};
3589
+ if ($previewInfo) {
3590
+ my $pt = \$previewInfo->{Data}; # image data or 'LOAD_PREVIEW' flag
3591
+ # now that we know the size of the EXIF data, first test to see if our new image fits
3592
+ # inside the EXIF segment (remember about the TIFF and EXIF headers: 8+6 bytes)
3593
+ if (($$pt ne 'LOAD_PREVIEW' and length($$pt) + length($newData) + 14 <= 0xfffd and
3594
+ not $previewInfo->{IsTrailer}) or
3595
+ $previewInfo->{IsShort}) # must fit in this segment if using short pointers
3596
+ {
3597
+ # It fits! (or must exist in EXIF segment), so fixup the
3598
+ # PreviewImage pointers and stuff the preview image in here
3599
+ my $newPos = length($newData) + $newDataPos;
3600
+ $newPos += ($previewInfo->{BaseShift} || 0);
3601
+ if ($previewInfo->{Relative}) {
3602
+ # calculate our base by looking at how far the pointer got shifted
3603
+ $newPos -= ($fixup->GetMarkerPointers(\$newData, 'PreviewImage') || 0);
3604
+ }
3605
+ $fixup->SetMarkerPointers(\$newData, 'PreviewImage', $newPos);
3606
+ $newData .= $$pt;
3607
+ # set flag to delete old preview unless it was contained in the EXIF
3608
+ $exifTool->{DEL_PREVIEW} = 1 unless $exifTool->{PREVIEW_INFO}{WasContained};
3609
+ delete $exifTool->{PREVIEW_INFO}; # done with our preview data
3610
+ } else {
3611
+ # Doesn't fit, or we still don't know, so save fixup information
3612
+ # and put the preview at the end of the file
3613
+ $previewInfo->{Fixup} or $previewInfo->{Fixup} = new Image::ExifTool::Fixup;
3614
+ $previewInfo->{Fixup}->AddFixup($fixup);
3615
+ }
3616
+ } elsif (defined $newData and $deleteAll) {
3617
+ $newData = ''; # delete both IFD0 and IFD1 since only mandatory tags remain
3618
+ } elsif ($$exifTool{A100PreviewLength}) {
3619
+ # save preview image start for patching A100 quirks later
3620
+ $$exifTool{A100PreviewStart} = $fixup->GetMarkerPointers(\$newData, 'PreviewImage');
3621
+ }
3622
+ # save location of last IFD for use in Canon RAW header
3623
+ if ($newDataPos == 16) {
3624
+ my @ifdPos = $fixup->GetMarkerPointers(\$newData,'NextIFD');
3625
+ $$origDirInfo{LastIFD} = pop @ifdPos;
3626
+ }
3627
+ # recrypt SR2 SubIFD data if necessary
3628
+ my $key = $$exifTool{SR2SubIFDKey};
3629
+ if ($key) {
3630
+ my $start = $fixup->GetMarkerPointers(\$newData, 'SR2SubIFDOffset');
3631
+ my $len = $$exifTool{SR2SubIFDLength};
3632
+ # (must subtract 8 for size of TIFF header)
3633
+ if ($start and $start - 8 + $len <= length $newData) {
3634
+ require Image::ExifTool::Sony;
3635
+ Image::ExifTool::Sony::Decrypt(\$newData, $start - 8, $len, $key);
3636
+ }
3637
+ }
3638
+ }
3639
+ # return empty string if no entries in directory
3640
+ # (could be up to 10 bytes and still be empty)
3641
+ $newData = '' if defined $newData and length($newData) < 12;
3642
+
3643
+ return $newData; # return our directory data
3644
+ }
3645
+
3646
+ 1; # end
3647
+
3648
+ __END__
3649
+
3650
+ =head1 NAME
3651
+
3652
+ Image::ExifTool::WriteExif.pl - Write EXIF meta information
3653
+
3654
+ =head1 SYNOPSIS
3655
+
3656
+ This file is autoloaded by Image::ExifTool::Exif.
3657
+
3658
+ =head1 DESCRIPTION
3659
+
3660
+ This file contains routines to write EXIF metadata.
3661
+
3662
+ =head1 AUTHOR
3663
+
3664
+ Copyright 2003-2013, Phil Harvey (phil at owl.phy.queensu.ca)
3665
+
3666
+ This library is free software; you can redistribute it and/or modify it
3667
+ under the same terms as Perl itself.
3668
+
3669
+ =head1 SEE ALSO
3670
+
3671
+ L<Image::ExifTool::Exif(3pm)|Image::ExifTool::Exif>,
3672
+ L<Image::ExifTool(3pm)|Image::ExifTool>
3673
+
3674
+ =cut